Advanced ipc - dbus details

Keywords: Linux DBus TCP/IP

What is IPC

IPC [inter process communication] interprocess communication refers to some technologies or methods for transmitting data or signals between at least two processes or threads. In Linux/Unix, many IPC are provided. Seven IPC of UNIX:

  • Pipe: nameless pipe, the most basic IPC, one-way communication, only between parent / child processes, that is, the output of one program is directly handed over to the input of another program. The common use is ps -ef|grep xxx
  • FIFO [(First in, First out)] or named pipe: unlike Pipe, FIFO allows two unrelated processes to use FIFO. One way.
  • Socket and Unix Domain Socket: socket and Unix socket, bidirectional. It is suitable for network communication, but it can also be used locally. Applicable to different protocols.
  • Message Queue: SysV message queue, POSIX message queue.
  • Signal: a signal is a specific behavior that sends a notification to a running process to trigger its events. It is a limited form of IPC.
  • Semaphore: semaphore, usually used for IPC or inter thread communication within the same process. Queues are used between them for message delivery, control, or content delivery. (common SysV semaphores and POSIX semaphores)
  • Shared memory: (common SysV shared memory and POSIX shared memory). Shared memory is an effective way to transfer data between processes (programs) in order to provide communication between them.

Each kind of IPC has its own characteristics, and each method has no effect on the use and performance of resources

  • Pipeline I/O is the fastest, but it is one-way communication and needs to work between parent / child processes.
  • UNIX sockets can connect different processes locally, have higher bandwidth, and have no inherent message boundaries.
  • TCP/IP sockets can connect to any process. And it can be connected through the network, but it will cost more resources. Similarly, there is no fixed message boundary.

Reference

comparsion Unix/Linux IPC

What is D-Bus

When it comes to freedesktop, D-Bus has to mention freedesktop, and D-Bus is only a part of freedesktop.org.

D-Bus is short for desktop bus, which is also the Linux IPC mechanism. Different from the seven basic IPC of UNIX, D-Bus is a middleware IPC implemented on these IPC types. D-Bus uses one or more of the basic IPC. Its design purpose is to provide service standardization in the Linux desktop environment. But it is not integrated into the mainline kernel at present.

As a middleware IPC, the performance of D-Bus is lower than that of other IPC modes, because there are many context switches in the communication process. If a message is sent through Dbus, it will be sent to the kernel first, and then sent back to D-Bus. AF_BUS patch is a new socket type to reduce D-Bus context switching.

For more information: https://en.wikipedia.org/wiki/D-Bus

D-Bus composition

D-Bus is an implementation of IPC, which is divided into three layers in architecture.

  • Layer 1 libdbus: a free and open source low-level API written in C language provided by freedesktop organization. Is a library that provides dbus functionality. Is a low-level API bound by a high-level API.
  • Layer 2 dbus daemon: the IPC daemon implemented by dbus is started with Linux, and the routing of messages between multiple processes (including kernel, network, desktop, etc.) is realized through the connection of non processes
  • Layer 3 Wapper libraries (high-level API): the encapsulation of low-level API libdbus, such as libdbus QT libdbus Python github.com/godbus/dbus. These wappers implemented in different programming languages are LIBS that different developers should use, which simplifies the development difficulty of D-Bus.

Reference

dbus-tutorial

Basic concepts of dbus

Bus

In D-Bus, bus is a core concept. It is a channel through which an application can make method calls, send signals, and listen for signals. There are two predefined buses: session bus and system bus.

  • Session Bus: it is created by an ordinary process, and multiple can exist at the same time. The Session Bus is private to a process and is used to pass messages between processes.

  • System Bus: it will be started at boot time. It is used by the operating system and background processes. It has very good security so that any application can not cheat system events. Of course, if an application needs to accept messages from the System Bus, it can also be directly connected to the System Bus, but the messages it can send are limited. The most common use of the System Bus is to send system wide notifications when system wide events occur. Adding new storage devices, network connection change events, and shutdown related events are examples of when the System Bus is better suited for the communication bus.

Generally, there is only one System Bus, but there can be multiple session buses (one for each desktop session).

The bus exists in the system in the form of DBUS daemon, which specially transfers messages from one process to another. The daemon will also forward notifications to all applications on the bus.

bus name

bus name cannot be understood only by literal bus name. The official interpretation of bus name is: * * * Connections have one or more bus names associated with them. A connection has exactly one bus name that is a unique connection name. * * * *. It can be seen that bus name is actually a connection name. It is mainly used to identify the connection between an application and the message bus. Bus names are mainly divided into two categories: unique names and public names.

  • unique connection names: bus name starting with a colon (':') character is a unique connection name. For example: 1.0. Each connection has a unique name. During the lifetime of a message bus, no two connections will have the same unique name.
  • Public connection name well-known bus names: the public name is based on the reverse DNS domain name (lower case), for example: org.fedoraproject.FirewallD1.
    • If the DNS domain name contains hyphens / minus signs, it should be replaced with underscores. If it contains numbers, it should be escaped by adding underscores. For example, the bus name of 7-zip.org should be defined as org_ 7_ zip.Archiver.

Reference

bus name

Object path

Object paths are the names used to reference object instances (similar to C + + or Java objects). Conceptually, each participant in D-Bus has any object instance in message exchange. Like the file system, the object instance in the participant in Dbus will also form a hierarchical tree. For example, in CentOS7, the D-Bus API developed by firewalld uses the hierarchy of / org/fedoraproject/FirewallD1.

When defining an object path, you should pay attention to the following:

  • The path can be any length
  • The path must begin with an ASCII '/' (integer 47) character and must consist of elements separated by slash characters.
  • Each element can contain only ASCII characters [AZ][az][0-9]_
  • Empty strings are not allowed
  • Multiple / characters cannot appear in sequence. Trailing / characters are not allowed unless the path is the root path (single / character).

Interface name

Interface. Each Object Path contains multiple interfaces. Generally, the interface name should start with the reverse DNS domain name (lower case), (the same as the interface name in Java). In terms of naming rules, it is the same as bus name.

For example, the D-Bus API developed by firewalld in CentOS7 defines the interface org.fedoraproject.FirewallD1.config.zone for managing zones. If the DNS name contains -, it should be replaced with an underscore. If the DNS domain name contains a number immediately after,. The interface name should be preceded by an underscore. For example, if the 7-zip.org plug-in defines an interface, it should be named org_ 7_ zip.Plugin.

Member method name

The member method name, Member names, needs to implement the implementation of the interface after the interface is defined. If you need to obtain the firewalld zone, you can call org.fedoraproject.FirewallD1.getDefaultZone. In D-Bus, Member names are usually named by "camel case".

dbus

In Linux, such as CentOS, DBUS includes dbus daemon and some cli Commons. These bags

dbuslib

D-Bus message

The most basic D-Bus protocol is one-to-one communication protocol. Different from using socket directly, D-Bus is a message oriented protocol. All functions of D-Bus are accomplished through messages flowing over the connection.

There are four types of messages in D-Bus

  • METHOD_CALL method call
  • METHOD_ The return method returns
  • ERROR error
  • SIGNAL: unlike method calls, SIGNAL emission does not respond. SIGNAL transmission is just a message of type SIGNAL. It must have three header fields: PATH to the object that sends the SIGNAL, plus INTERFACE, and MEMBER to give the fully qualified name of the SIGNAL.

The type of message returned

Conventional nameDecimal valueexplain
INVALID0This is an invalid type
METHOD_CALL1Method is called, and the method will be prompted
METHOD_RETURN2Method
ERROR3Error return, the first is its error information
SIGNAL4Signal transmission

dbus service management of CentOS

In CentOS7, as part of SYSTEMd, D-Bus obtains socket file descriptors from SYSTEMd and uses D-Bus to exchange socket information generated by the current process. PID 1 does not use PolicyKit to control access to privileged operations, but completely depends on low-level API D-Bus. (this is done to avoid the circular dependency between PolicyKit and systemd/PID 1.) some privileged processes (such as shutdown / restart / suspend / login) can be managed through logind.

From this, we can know that in CentOS, dbus related services probably include dbus and logind.

dbus contains:

  • dbus-daemon : dbus Damon of layer 2 in dbus architecture

  • dbus-send : the command line tool provided by dbus can send messages with dbus send.

  • dbus-monitor : command line tool provided by dbus to monitor messages flowing on the bus.

  • dbus-launch : the shell script starts the command line tool for the message bus

dbus profile description

The DBUS daemon has two configuration files, one is session bus and the other is system bus.

The standard system bus file / usr / local / share / dbus-1 / system.conf is configured in / usr/local/share/dbus-1/session.conf. In general, these two files are not manipulated because they introduce system.conf or session.conf in / etc/dbus-1.

Labels included in the configuration file:

For more notes, please refer to: dbus-daemon

# Root element
<busconfig>

  <!-- According to the specified -system or -session To select your profile -->
  <type>system</type>

  <!-- dbus-daemon User running -->
  <user>dbus</user>

  <!-- Fork into daemon mode -->
  <fork/>

  <!-- We use system service launching using a helper -->
  <standard_system_servicedirs/>

  <!-- This is a setuid helper that is used to launch system services -->
  <servicehelper>//usr/libexec/dbus-1/dbus-daemon-launch-helper</servicehelper>

  <!-- Write a pid file -->
  <pidfile>/run/dbus/messagebus.pid</pidfile>

  <!-- Enable logging to syslog -->
  <syslog/>

  <!-- Specify the authorization mechanism. If not, all mechanisms are allowed. -->
  <auth>EXTERNAL</auth>

  <!-- Address of bus monitoring, support unix socket,tcp,system etc.
		-->
  <listen>unix:path=/run/dbus/system_bus_socket</listen>
  <listen>unix:path=/tmp/foo</listen>
  <listen>tcp:host=localhost,port=1234</listen>  
    
    
  <policy context="default">
    <!-- All users can connect to system bus -->
    <allow user="*"/>

    <!-- Holes must be punched in service configuration files for
         name ownership and sending method calls -->
    <deny own="*"/>
    <deny send_type="method_call"/>

    <!-- Signals and reply messages (method returns, errors) are allowed
         by efault -->
    <allow send_type="signal"/>
    <allow send_requested_reply="true" send_type="method_return"/>
    <allow send_requested_reply="true" send_type="error"/>

    <!-- All messages may be received by default -->
    <allow receive_type="method_call"/>
    <allow receive_type="method_return"/>
    <allow receive_type="error"/>
    <allow receive_type="signal"/>

    <!-- Allow anyone to talk to the message bus -->
    <allow send_destination="org.freedesktop.DBus"
           send_interface="org.freedesktop.DBus" />
    <allow send_destination="org.fedoraproject.FirewallD1" 
	send_interface="org.fedorapproject.FirewallD1" />
    <allow send_destination="org.freedesktop.DBus"
           send_interface="org.freedesktop.DBus.Introspectable"/>
    <!-- But disallow some specific bus services -->
    <deny send_destination="org.freedesktop.DBus"
          send_interface="org.freedesktop.DBus"
          send_member="UpdateActivationEnvironment"/>
    <deny send_destination="org.freedesktop.DBus"
          send_interface="org.freedesktop.DBus.Debug.Stats"/>
    <deny send_destination="org.freedesktop.DBus"
          send_interface="org.freedesktop.systemd1.Activator"/>
  </policy>

  <!-- Only systemd, which runs as root, may report activation failures. -->
  <policy user="root">
    <allow send_destination="org.freedesktop.DBus"
           send_interface="org.freedesktop.systemd1.Activator"/>
  </policy>

  <!-- root may monitor the system bus. -->
  <policy user="root">
    <allow send_destination="org.freedesktop.DBus"
           send_interface="org.freedesktop.DBus.Monitoring"/>
  </policy>

  <!-- If the Stats interface was enabled at compile-time, root may use it.
       Copy this into system.local.conf or system.d/*.conf if you want to
       enable other privileged users to view statistics and debug info -->
  <policy user="root">
    <allow send_destination="org.freedesktop.DBus"
           send_interface="org.freedesktop.DBus.Debug.Stats"/>
  </policy>

  <!-- Include legacy configuration location -->
  <include ignore_missing="yes">/etc/dbus-1/system.conf</include>

  <!-- Included sub profiles. -->
  <includedir>system.d</includedir>

  <includedir>/etc/dbus-1/system.d</includedir>

  <!-- This is included last so local configuration can override what's 
       in this standard file -->
  <include ignore_missing="yes">/etc/dbus-1/system-local.conf</include>

  <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>

</busconfig>

Sending dbus messages from the command line

dbus supports sending a dbus message through commands, such as obtaining available dbus services.

dbus-send --session \
--dest=org.freedesktop.DBus \
--type=method_call \
--print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.ListNames

method return time=1631452206.288425 sender=org.freedesktop.DBus -> destination=:1.29 serial=3 reply_serial=2
   array [
      string "org.freedesktop.DBus"
      string "org.freedesktop.login1"
      string "org.freedesktop.systemd1"
      string "org.fedoraproject.FirewallD1"
      string "org.freedesktop.PolicyKit1"
      string ":1.17"
      string ":1.0"
      string ":1.29"
      string ":1.18"
      string ":1.1"
   ]

Return to org.freedesktop.DBus service

dbus-send --session \
--dest=org.freedesktop.DBus \
--type=method_call \
--print-reply \
/org/freedesktop/DBus \
org.freedesktop.DBus.Introspectable.Introspect

Operating linux firewall using dbus api

Firewall is a firewall daemon based on dynamic zone. It has been developed since around 2009. At present, it is the default firewall mechanism in Fedora 18 and subsequent RHEL7 and CentOS 7.

Firewall is configured as a SYSTEMd D D-Bus service. Note the "Type=dbus" directive below.

# cat /usr/lib/systemd/system/firewalld.service 
[Unit]
Description=firewalld - dynamic firewall daemon
Before=network.target
Before=libvirtd.service
Before=NetworkManager.service
Conflicts=iptables.service ip6tables.service ebtables.service

[Service]
EnvironmentFile=-/etc/sysconfig/firewalld
ExecStart=/usr/sbin/firewalld --nofork --nopid $FIREWALLD_ARGS
ExecReload=/bin/kill -HUP $MAINPID
# supress to log debug and error output also to /var/log/messages
StandardOutput=null
StandardError=null
Type=dbus
BusName=org.fedoraproject.FirewallD1

[Install]
WantedBy=basic.target
Alias=dbus-org.fedoraproject.FirewallD1.service

Knowing that the firewalld service is based on D-Bus, you can operate the firewall through D-Bus.

Check whether the service registered by dbus contains firewalld. It should be noted here that firewalld depends on the dbus service and is registered in the dbus bus every time firewalld is started. Therefore, you need to start the dbus daemon and firewalld services first.

dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply \
/org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep FirewallD

You can see that org.fedoraproject.FirewallD1 is the firewalld interface

View the method, attribute, signal and other information owned by the interface

dbus-send --system --dest=org.fedoraproject.FirewallD1 --print-reply \
/org/fedoraproject/FirewallD1 org.freedesktop.DBus.Introspectable.Introspect

Get zone

firewall-cmd --get-zones

dbus-send --system \
--dest=org.fedoraproject.FirewallD1 \
--print-reply \
--type=method_call /org/fedoraproject/FirewallD1 \
org.fedoraproject.FirewallD1.zone.getZones

View the entry information in the zone

# firewall-cmd --zone=public --list-all

dbus-send --system --dest=org.fedoraproject.FirewallD1 --print-reply --type=method_call \
/org/fedoraproject/FirewallD1 org.fedoraproject.FirewallD1.getZoneSettings string:"public"

Posted by joel danny on Sat, 09 Oct 2021 02:54:07 -0700