chiark / gitweb /
unit: save description/slice of transient units to /run
[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_UNIT_CGROUP_INTERFACE                                       \
38         BUS_EXEC_COMMAND_INTERFACE("ExecStartPre")                      \
39         BUS_EXEC_COMMAND_INTERFACE("ExecStartPost")                     \
40         BUS_EXEC_COMMAND_INTERFACE("ExecStopPre")                       \
41         BUS_EXEC_COMMAND_INTERFACE("ExecStopPost")                      \
42         BUS_EXEC_CONTEXT_INTERFACE                                      \
43         BUS_KILL_CONTEXT_INTERFACE                                      \
44         BUS_CGROUP_CONTEXT_INTERFACE                                    \
45         "  <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \
46         "  <property name=\"BindToDevice\" type=\"s\" access=\"read\"/>\n" \
47         "  <property name=\"DirectoryMode\" type=\"u\" access=\"read\"/>\n" \
48         "  <property name=\"SocketMode\" type=\"u\" access=\"read\"/>\n" \
49         "  <property name=\"Accept\" type=\"b\" access=\"read\"/>\n"    \
50         "  <property name=\"KeepAlive\" type=\"b\" access=\"read\"/>\n" \
51         "  <property name=\"Priority\" type=\"i\" access=\"read\"/>\n"  \
52         "  <property name=\"ReceiveBuffer\" type=\"t\" access=\"read\"/>\n" \
53         "  <property name=\"SendBuffer\" type=\"t\" access=\"read\"/>\n" \
54         "  <property name=\"IPTOS\" type=\"i\" access=\"read\"/>\n"     \
55         "  <property name=\"IPTTL\" type=\"i\" access=\"read\"/>\n"     \
56         "  <property name=\"PipeSize\" type=\"t\" access=\"read\"/>\n"  \
57         "  <property name=\"FreeBind\" type=\"b\" access=\"read\"/>\n"  \
58         "  <property name=\"Transparent\" type=\"b\" access=\"read\"/>\n" \
59         "  <property name=\"Broadcast\" type=\"b\" access=\"read\"/>\n" \
60         "  <property name=\"PassCredentials\" type=\"b\" access=\"read\"/>\n" \
61         "  <property name=\"PassSecurity\" type=\"b\" access=\"read\"/>\n" \
62         "  <property name=\"Mark\" type=\"i\" access=\"read\"/>\n"      \
63         "  <property name=\"MaxConnections\" type=\"u\" access=\"read\"/>\n" \
64         "  <property name=\"NAccepted\" type=\"u\" access=\"read\"/>\n" \
65         "  <property name=\"NConnections\" type=\"u\" access=\"read\"/>\n" \
66         "  <property name=\"MessageQueueMaxMessages\" type=\"x\" access=\"read\"/>\n" \
67         "  <property name=\"MessageQueueMessageSize\" type=\"x\" access=\"read\"/>\n" \
68         "  <property name=\"Listen\" type=\"a(ss)\" access=\"read\"/>\n"    \
69         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
70         "  <property name=\"SmackLabel\" type=\"s\" access=\"read\"/>\n" \
71         "  <property name=\"SmackLabelIPIn\" type=\"s\" access=\"read\"/>\n" \
72         "  <property name=\"SmackLabelIPOut\" type=\"s\" access=\"read\"/>\n" \
73         " </interface>\n"                                               \
74
75 #define INTROSPECTION                                                   \
76         DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
77         "<node>\n"                                                      \
78         BUS_UNIT_INTERFACE                                              \
79         BUS_SOCKET_INTERFACE                                            \
80         BUS_PROPERTIES_INTERFACE                                        \
81         BUS_PEER_INTERFACE                                              \
82         BUS_INTROSPECTABLE_INTERFACE                                    \
83         "</node>\n"
84
85 #define INTERFACES_LIST                              \
86         BUS_UNIT_INTERFACES_LIST                     \
87         "org.freedesktop.systemd1.Socket\0"
88
89 const char bus_socket_interface[] _introspect_("Socket") = BUS_SOCKET_INTERFACE;
90
91 const char bus_socket_invalidating_properties[] =
92         "ExecStartPre\0"
93         "ExecStartPost\0"
94         "ExecStopPre\0"
95         "ExecStopPost\0"
96         "ControlPID\0"
97         "NAccepted\0"
98         "NConnections\0"
99         "Result\0";
100
101 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
102 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_socket_append_socket_result, socket_result, SocketResult);
103
104 static int bus_socket_append_listen(DBusMessageIter *i, const char *property, void *data) {
105
106         Socket *s = SOCKET(data);
107         SocketPort *p;
108         DBusMessageIter array, stru;
109
110         assert(data);
111         assert(property);
112         assert(s);
113
114         if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(ss)", &array))
115                 return log_oom();
116
117         LIST_FOREACH(port, p, s->ports) {
118                 const char *type = socket_port_type_to_string(p);
119                 _cleanup_free_ char *address = NULL;
120                 const char *a;
121
122                 if (!dbus_message_iter_open_container(&array, DBUS_TYPE_STRUCT, NULL, &stru))
123                         return log_oom();
124
125                 if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &type))
126                         return log_oom();
127
128                 switch (p->type) {
129                         case SOCKET_SOCKET: {
130                                 int r;
131
132                                 r = socket_address_print(&p->address, &address);
133                                 if (r) {
134                                         log_error("socket_address_print failed: %s", strerror(-r));
135                                         return r;
136                                 }
137                                 a = address;
138                                 break;
139                         }
140
141                         case SOCKET_SPECIAL:
142                         case SOCKET_MQUEUE:
143                         case SOCKET_FIFO:
144                                 a = p->path;
145                                 break;
146
147                         default:
148                                 a = type;
149                 }
150
151                 if (!dbus_message_iter_append_basic(&stru, DBUS_TYPE_STRING, &a))
152                         return -ENOMEM;
153
154                 if (!dbus_message_iter_close_container(&array, &stru))
155                         return -ENOMEM;
156         }
157
158         if (!dbus_message_iter_close_container(i, &array))
159                 return -ENOMEM;
160
161         return 0;
162 }
163
164 static const BusProperty bus_socket_properties[] = {
165         { "BindIPv6Only",   bus_socket_append_bind_ipv6_only,  "s", offsetof(Socket, bind_ipv6_only)  },
166         { "Backlog",        bus_property_append_unsigned,      "u", offsetof(Socket, backlog)         },
167         { "TimeoutUSec",    bus_property_append_usec,          "t", offsetof(Socket, timeout_usec)    },
168         BUS_EXEC_COMMAND_PROPERTY("ExecStartPre",  offsetof(Socket, exec_command[SOCKET_EXEC_START_PRE]),  true ),
169         BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Socket, exec_command[SOCKET_EXEC_START_POST]), true ),
170         BUS_EXEC_COMMAND_PROPERTY("ExecStopPre",   offsetof(Socket, exec_command[SOCKET_EXEC_STOP_PRE]),   true ),
171         BUS_EXEC_COMMAND_PROPERTY("ExecStopPost",  offsetof(Socket, exec_command[SOCKET_EXEC_STOP_POST]),  true ),
172         { "ControlPID",     bus_property_append_pid,           "u", offsetof(Socket, control_pid)     },
173         { "BindToDevice",   bus_property_append_string,        "s", offsetof(Socket, bind_to_device), true },
174         { "DirectoryMode",  bus_property_append_mode,          "u", offsetof(Socket, directory_mode)  },
175         { "SocketMode",     bus_property_append_mode,          "u", offsetof(Socket, socket_mode)     },
176         { "Accept",         bus_property_append_bool,          "b", offsetof(Socket, accept)          },
177         { "KeepAlive",      bus_property_append_bool,          "b", offsetof(Socket, keep_alive)      },
178         { "Priority",       bus_property_append_int,           "i", offsetof(Socket, priority)        },
179         { "ReceiveBuffer",  bus_property_append_size,          "t", offsetof(Socket, receive_buffer)  },
180         { "SendBuffer",     bus_property_append_size,          "t", offsetof(Socket, send_buffer)     },
181         { "IPTOS",          bus_property_append_int,           "i", offsetof(Socket, ip_tos)          },
182         { "IPTTL",          bus_property_append_int,           "i", offsetof(Socket, ip_ttl)          },
183         { "PipeSize",       bus_property_append_size,          "t", offsetof(Socket, pipe_size)       },
184         { "FreeBind",       bus_property_append_bool,          "b", offsetof(Socket, free_bind)       },
185         { "Transparent",    bus_property_append_bool,          "b", offsetof(Socket, transparent)     },
186         { "Broadcast",      bus_property_append_bool,          "b", offsetof(Socket, broadcast)       },
187         { "PassCredentials",bus_property_append_bool,          "b", offsetof(Socket, pass_cred)       },
188         { "PassSecurity",   bus_property_append_bool,          "b", offsetof(Socket, pass_sec)        },
189         { "Listen",         bus_socket_append_listen,      "a(ss)", 0,                                },
190         { "Mark",           bus_property_append_int,           "i", offsetof(Socket, mark)            },
191         { "MaxConnections", bus_property_append_unsigned,      "u", offsetof(Socket, max_connections) },
192         { "NConnections",   bus_property_append_unsigned,      "u", offsetof(Socket, n_connections)   },
193         { "NAccepted",      bus_property_append_unsigned,      "u", offsetof(Socket, n_accepted)      },
194         { "MessageQueueMaxMessages", bus_property_append_long, "x", offsetof(Socket, mq_maxmsg)       },
195         { "MessageQueueMessageSize", bus_property_append_long, "x", offsetof(Socket, mq_msgsize)      },
196         { "Result",         bus_socket_append_socket_result,   "s", offsetof(Socket, result)          },
197         { "SmackLabel",     bus_property_append_string,        "s", offsetof(Socket, smack),          true },
198         { "SmackLabelIPIn", bus_property_append_string,        "s", offsetof(Socket, smack_ip_in),    true },
199         { "SmackLabelIPOut",bus_property_append_string,        "s", offsetof(Socket, smack_ip_out),   true },
200         {}
201 };
202
203 DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
204         Socket *s = SOCKET(u);
205         const BusBoundProperties bps[] = {
206                 { "org.freedesktop.systemd1.Unit",   bus_unit_properties,           u },
207                 { "org.freedesktop.systemd1.Socket", bus_unit_cgroup_properties,    u },
208                 { "org.freedesktop.systemd1.Socket", bus_socket_properties,         s },
209                 { "org.freedesktop.systemd1.Socket", bus_exec_context_properties,   &s->exec_context },
210                 { "org.freedesktop.systemd1.Socket", bus_kill_context_properties,   &s->kill_context },
211                 { "org.freedesktop.systemd1.Socket", bus_cgroup_context_properties, &s->cgroup_context },
212                 {}
213         };
214
215         SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
216
217         return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
218 }
219
220 int bus_socket_set_property(
221                 Unit *u,
222                 const char *name,
223                 DBusMessageIter *i,
224                 UnitSetPropertiesMode mode,
225                 DBusError *error) {
226
227         Socket *s = SOCKET(u);
228         int r;
229
230         assert(name);
231         assert(u);
232         assert(i);
233
234         r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
235         if (r != 0)
236                 return r;
237
238         return 0;
239 }
240
241 int bus_socket_commit_properties(Unit *u) {
242         assert(u);
243
244         unit_realize_cgroup(u);
245         return 0;
246 }