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