chiark / gitweb /
core: add new "scope" unit type for making a unit of pre-existing processes
[elogind.git] / src / core / dbus-socket.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23
24 #include "dbus-unit.h"
25 #include "dbus-execute.h"
26 #include "dbus-kill.h"
27 #include "dbus-cgroup.h"
28 #include "dbus-common.h"
29 #include "selinux-access.h"
30 #include "dbus-socket.h"
31
32 #define BUS_SOCKET_INTERFACE                                            \
33         " <interface name=\"org.freedesktop.systemd1.Socket\">\n"       \
34         "  <property name=\"BindIPv6Only\" type=\"b\" access=\"read\"/>\n" \
35         "  <property name=\"Backlog\" type=\"u\" access=\"read\"/>\n"   \
36         "  <property name=\"TimeoutUSec\" type=\"t\" access=\"read\"/>\n" \
37         BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
38         BUS_EXEC_COMMAND_INTERFACE("ExecStartPost")                     \
39         BUS_EXEC_COMMAND_INTERFACE("ExecStopPre")                       \
40         BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
41         BUS_EXEC_CONTEXT_INTERFACE                                      \
42         BUS_KILL_CONTEXT_INTERFACE                                      \
43         BUS_CGROUP_CONTEXT_INTERFACE                                    \
44         "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
45         "  <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
46         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
47         "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
48         "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
49         "  <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
50         "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
51         "  <property name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
52         "  <property name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
53         "  <property name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
54         "  <property name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
55         "  <property name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
56         "  <property name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
57         "  <property name=\"Transparent\" type=\"b\" access=\"read\"/>\n" \
58         "  <property name=\"Broadcast\" type=\"b\" access=\"read\"/>\n" \
59         "  <property name=\"PassCredentials\" type=\"b\" access=\"read\"/>\n" \
60         "  <property name=\"PassSecurity\" type=\"b\" access=\"read\"/>\n" \
61         "  <property name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
62         "  <property name=\"MaxConnections\" type=\"u\" access=\"read\"/>\n" \
63         "  <property name=\"NAccepted\" type=\"u\" access=\"read\"/>\n" \
64         "  <property name=\"NConnections\" type=\"u\" access=\"read\"/>\n" \
65         "  <property name=\"MessageQueueMaxMessages\" type=\"x\" access=\"read\"/>\n" \
66         "  <property name=\"MessageQueueMessageSize\" type=\"x\" access=\"read\"/>\n" \
67         "  <property name=\"Listen\" type=\"a(ss)\" access=\"read\"/>\n"    \
68         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
69         "  <property name=\"SmackLabel\" type=\"s\" access=\"read\"/>\n" \
70         "  <property name=\"SmackLabelIPIn\" type=\"s\" access=\"read\"/>\n" \
71         "  <property name=\"SmackLabelIPOut\" type=\"s\" access=\"read\"/>\n" \
72         " </interface>\n"                                               \
73
74 #define INTROSPECTION                                                   \
75         DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
76         "<node>\n"                                                      \
77         BUS_UNIT_INTERFACE                                              \
78         BUS_SOCKET_INTERFACE                                            \
79         BUS_PROPERTIES_INTERFACE                                        \
80         BUS_PEER_INTERFACE                                              \
81         BUS_INTROSPECTABLE_INTERFACE                                    \
82         "</node>\n"
83
84 #define INTERFACES_LIST                              \
85         BUS_UNIT_INTERFACES_LIST                     \
86         "org.freedesktop.systemd1.Socket\0"
87
88 const char bus_socket_interface[] _introspect_("Socket") = BUS_SOCKET_INTERFACE;
89
90 const char bus_socket_invalidating_properties[] =
91         "ExecStartPre\0"
92         "ExecStartPost\0"
93         "ExecStopPre\0"
94         "ExecStopPost\0"
95         "ControlPID\0"
96         "NAccepted\0"
97         "NConnections\0"
98         "Result\0";
99
100 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
101 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_socket_result, socket_result, SocketResult);
102
103 static int bus_socket_append_listen(DBusMessageIter *i, const char *property, void *data) {
104
105         Socket *s = SOCKET(data);
106         SocketPort *p;
107         DBusMessageIter array, stru;
108
109         assert(data);
110         assert(property);
111         assert(s);
112
113         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &array))
114                 return log_oom();
115
116         LIST_FOREACH(port, p, s->ports) {
117                 const char *type = socket_port_type_to_string(p);
118                 _cleanup_free_ char *address = NULL;
119                 const char *a;
120
121                 if (!dbus_message_iter_open_container(&array, DBUS_TYPE_STRUCT, NULL, &stru))
122                         return log_oom();
123
124                 if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &type))
125                         return log_oom();
126
127                 switch (p->type) {
128                         case SOCKET_SOCKET: {
129                                 int r;
130
131                                 r = socket_address_print(&p->address, &address);
132                                 if (r) {
133                                         log_error("socket_address_print failed: %s", strerror(-r));
134                                         return r;
135                                 }
136                                 a = address;
137                                 break;
138                         }
139
140                         case SOCKET_SPECIAL:
141                         case SOCKET_MQUEUE:
142                         case SOCKET_FIFO:
143                                 a = p->path;
144                                 break;
145
146                         default:
147                                 a = type;
148                 }
149
150                 if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &a))
151                         return -ENOMEM;
152
153                 if (!dbus_message_iter_close_container(&array, &stru))
154                         return -ENOMEM;
155         }
156
157         if (!dbus_message_iter_close_container(i, &array))
158                 return -ENOMEM;
159
160         return 0;
161 }
162
163 static const BusProperty bus_socket_properties[] = {
164         { "BindIPv6Only",   bus_socket_append_bind_ipv6_only,  "s", offsetof(Socket, bind_ipv6_only)  },
165         { "Backlog",        bus_property_append_unsigned,      "u", offsetof(Socket, backlog)         },
166         { "TimeoutUSec",    bus_property_append_usec,          "t", offsetof(Socket, timeout_usec)    },
167         BUS_EXEC_COMMAND_PROPERTY("ExecStartPre",  offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]),  true ),
168         BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), true ),
169         BUS_EXEC_COMMAND_PROPERTY("ExecStopPre",   offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]),   true ),
170         BUS_EXEC_COMMAND_PROPERTY("ExecStopPost",  offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]),  true ),
171         { "ControlPID",     bus_property_append_pid,           "u", offsetof(Socket, control_pid)     },
172         { "BindToDevice",   bus_property_append_string,        "s", offsetof(Socket, bind_to_device), true },
173         { "DirectoryMode",  bus_property_append_mode,          "u", offsetof(Socket, directory_mode)  },
174         { "SocketMode",     bus_property_append_mode,          "u", offsetof(Socket, socket_mode)     },
175         { "Accept",         bus_property_append_bool,          "b", offsetof(Socket, accept)          },
176         { "KeepAlive",      bus_property_append_bool,          "b", offsetof(Socket, keep_alive)      },
177         { "Priority",       bus_property_append_int,           "i", offsetof(Socket, priority)        },
178         { "ReceiveBuffer",  bus_property_append_size,          "t", offsetof(Socket, receive_buffer)  },
179         { "SendBuffer",     bus_property_append_size,          "t", offsetof(Socket, send_buffer)     },
180         { "IPTOS",          bus_property_append_int,           "i", offsetof(Socket, ip_tos)          },
181         { "IPTTL",          bus_property_append_int,           "i", offsetof(Socket, ip_ttl)          },
182         { "PipeSize",       bus_property_append_size,          "t", offsetof(Socket, pipe_size)       },
183         { "FreeBind",       bus_property_append_bool,          "b", offsetof(Socket, free_bind)       },
184         { "Transparent",    bus_property_append_bool,          "b", offsetof(Socket, transparent)     },
185         { "Broadcast",      bus_property_append_bool,          "b", offsetof(Socket, broadcast)       },
186         { "PassCredentials",bus_property_append_bool,          "b", offsetof(Socket, pass_cred)       },
187         { "PassSecurity",   bus_property_append_bool,          "b", offsetof(Socket, pass_sec)        },
188         { "Listen",         bus_socket_append_listen,      "a(ss)", 0,                                },
189         { "Mark",           bus_property_append_int,           "i", offsetof(Socket, mark)            },
190         { "MaxConnections", bus_property_append_unsigned,      "u", offsetof(Socket, max_connections) },
191         { "NConnections",   bus_property_append_unsigned,      "u", offsetof(Socket, n_connections)   },
192         { "NAccepted",      bus_property_append_unsigned,      "u", offsetof(Socket, n_accepted)      },
193         { "MessageQueueMaxMessages", bus_property_append_long, "x", offsetof(Socket, mq_maxmsg)       },
194         { "MessageQueueMessageSize", bus_property_append_long, "x", offsetof(Socket, mq_msgsize)      },
195         { "Result",         bus_socket_append_socket_result,   "s", offsetof(Socket, result)          },
196         { "SmackLabel",     bus_property_append_string,        "s", offsetof(Socket, smack),          true },
197         { "SmackLabelIPIn", bus_property_append_string,        "s", offsetof(Socket, smack_ip_in),    true },
198         { "SmackLabelIPOut",bus_property_append_string,        "s", offsetof(Socket, smack_ip_out),   true },
199         { NULL, }
200 };
201
202 DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
203         Socket *s = SOCKET(u);
204         const BusBoundProperties bps[] = {
205                 { "org.freedesktop.systemd1.Unit",   bus_unit_properties,           u },
206                 { "org.freedesktop.systemd1.Socket", bus_socket_properties,         s },
207                 { "org.freedesktop.systemd1.Socket", bus_exec_context_properties,   &s->exec_context },
208                 { "org.freedesktop.systemd1.Socket", bus_kill_context_properties,   &s->kill_context },
209                 { "org.freedesktop.systemd1.Socket", bus_cgroup_context_properties, &s->cgroup_context },
210                 { NULL, }
211         };
212
213         SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
214
215         return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
216 }
217
218 int bus_socket_set_property(
219                 Unit *u,
220                 const char *name,
221                 DBusMessageIter *i,
222                 UnitSetPropertiesMode mode,
223                 DBusError *error) {
224
225         Socket *s = SOCKET(u);
226         int r;
227
228         assert(name);
229         assert(u);
230         assert(i);
231
232         r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
233         if (r != 0)
234                 return r;
235
236         return 0;
237 }
238
239 int bus_socket_commit_properties(Unit *u) {
240         assert(u);
241
242         unit_realize_cgroup(u);
243         return 0;
244 }