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