#include "services.h"
#include "selinux.h"
#include "signals.h"
+#include "stats.h"
#include "utils.h"
+
#include <dbus/dbus-string.h>
#include <dbus/dbus-internals.h>
#include <dbus/dbus-message.h>
#include <dbus/dbus-marshal-recursive.h>
#include <string.h>
+static DBusConnection *
+bus_driver_get_conn_helper (DBusConnection *connection,
+ DBusMessage *message,
+ const char *what_we_want,
+ const char **name_p,
+ DBusError *error)
+{
+ const char *name;
+ BusRegistry *registry;
+ BusService *serv;
+ DBusString str;
+ DBusConnection *conn;
+
+ if (!dbus_message_get_args (message, error,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_INVALID))
+ return NULL;
+
+ _dbus_assert (name != NULL);
+ _dbus_verbose ("asked for %s of connection %s\n", what_we_want, name);
+
+ registry = bus_connection_get_registry (connection);
+ _dbus_string_init_const (&str, name);
+ serv = bus_registry_lookup (registry, &str);
+
+ if (serv == NULL)
+ {
+ dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
+ "Could not get %s of name '%s': no such name",
+ what_we_want, name);
+ return NULL;
+ }
+
+ conn = bus_service_get_primary_owners_connection (serv);
+ _dbus_assert (conn != NULL);
+
+ if (name_p != NULL)
+ *name_p = name;
+
+ return conn;
+}
+
static dbus_bool_t bus_driver_send_welcome_message (DBusConnection *connection,
DBusMessage *hello_message,
BusTransaction *transaction,
DBusMessageIter iter;
DBusMessageIter dict_iter;
DBusMessageIter dict_entry_iter;
- int msg_type;
int array_type;
int key_type;
DBusList *keys, *key_link;
/* The message signature has already been checked for us,
* so let's just assert it's right.
*/
- msg_type = dbus_message_iter_get_arg_type (&iter);
+#ifndef DBUS_DISABLE_ASSERT
+ {
+ int msg_type = dbus_message_iter_get_arg_type (&iter);
- _dbus_assert (msg_type == DBUS_TYPE_ARRAY);
+ _dbus_assert (msg_type == DBUS_TYPE_ARRAY);
+ }
+#endif
dbus_message_iter_recurse (&iter, &dict_iter);
DBusMessage *message,
DBusError *error)
{
- const char *service;
- DBusString str;
- BusRegistry *registry;
- BusService *serv;
DBusConnection *conn;
DBusMessage *reply;
unsigned long uid;
dbus_uint32_t uid32;
+ const char *service;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- registry = bus_connection_get_registry (connection);
-
- service = NULL;
reply = NULL;
- if (! dbus_message_get_args (message, error,
- DBUS_TYPE_STRING, &service,
- DBUS_TYPE_INVALID))
- goto failed;
-
- _dbus_verbose ("asked for UID of connection %s\n", service);
-
- _dbus_string_init_const (&str, service);
- serv = bus_registry_lookup (registry, &str);
- if (serv == NULL)
- {
- dbus_set_error (error,
- DBUS_ERROR_NAME_HAS_NO_OWNER,
- "Could not get UID of name '%s': no such name", service);
- goto failed;
- }
+ conn = bus_driver_get_conn_helper (connection, message, "UID", &service,
+ error);
- conn = bus_service_get_primary_owners_connection (serv);
+ if (conn == NULL)
+ goto failed;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
DBusMessage *message,
DBusError *error)
{
- const char *service;
- DBusString str;
- BusRegistry *registry;
- BusService *serv;
DBusConnection *conn;
DBusMessage *reply;
unsigned long pid;
dbus_uint32_t pid32;
+ const char *service;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- registry = bus_connection_get_registry (connection);
-
- service = NULL;
reply = NULL;
- if (! dbus_message_get_args (message, error,
- DBUS_TYPE_STRING, &service,
- DBUS_TYPE_INVALID))
- goto failed;
+ conn = bus_driver_get_conn_helper (connection, message, "PID", &service,
+ error);
- _dbus_verbose ("asked for PID of connection %s\n", service);
-
- _dbus_string_init_const (&str, service);
- serv = bus_registry_lookup (registry, &str);
- if (serv == NULL)
- {
- dbus_set_error (error,
- DBUS_ERROR_NAME_HAS_NO_OWNER,
- "Could not get PID of name '%s': no such name", service);
- goto failed;
- }
-
- conn = bus_service_get_primary_owners_connection (serv);
+ if (conn == NULL)
+ goto failed;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
DBusMessage *message,
DBusError *error)
{
- const char *service;
- DBusString str;
- BusRegistry *registry;
- BusService *serv;
DBusConnection *conn;
DBusMessage *reply;
void *data = NULL;
dbus_uint32_t data_size;
+ const char *service;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- registry = bus_connection_get_registry (connection);
-
- service = NULL;
reply = NULL;
- if (! dbus_message_get_args (message, error,
- DBUS_TYPE_STRING, &service,
- DBUS_TYPE_INVALID))
- goto failed;
+ conn = bus_driver_get_conn_helper (connection, message,
+ "audit session data", &service, error);
- _dbus_verbose ("asked for audit session data for connection %s\n", service);
-
- _dbus_string_init_const (&str, service);
- serv = bus_registry_lookup (registry, &str);
- if (serv == NULL)
- {
- dbus_set_error (error,
- DBUS_ERROR_NAME_HAS_NO_OWNER,
- "Could not get audit session data for name '%s': no such name", service);
- goto failed;
- }
-
- conn = bus_service_get_primary_owners_connection (serv);
+ if (conn == NULL)
+ goto failed;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
DBusMessage *message,
DBusError *error)
{
- const char *service;
- DBusString str;
- BusRegistry *registry;
- BusService *serv;
DBusConnection *conn;
DBusMessage *reply;
BusSELinuxID *context;
+ const char *service;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
- registry = bus_connection_get_registry (connection);
-
- service = NULL;
reply = NULL;
- if (! dbus_message_get_args (message, error,
- DBUS_TYPE_STRING, &service,
- DBUS_TYPE_INVALID))
- goto failed;
-
- _dbus_verbose ("asked for security context of connection %s\n", service);
+ conn = bus_driver_get_conn_helper (connection, message, "security context",
+ &service, error);
- _dbus_string_init_const (&str, service);
- serv = bus_registry_lookup (registry, &str);
- if (serv == NULL)
- {
- dbus_set_error (error,
- DBUS_ERROR_NAME_HAS_NO_OWNER,
- "Could not get security context of name '%s': no such name", service);
- goto failed;
- }
-
- conn = bus_service_get_primary_owners_connection (serv);
+ if (conn == NULL)
+ goto failed;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
return FALSE;
}
-/* For speed it might be useful to sort this in order of
- * frequency of use (but doesn't matter with only a few items
- * anyhow)
- */
-static struct
+typedef struct
{
const char *name;
const char *in_args;
BusTransaction *transaction,
DBusMessage *message,
DBusError *error);
-} message_handlers[] = {
+} MessageHandler;
+
+/* For speed it might be useful to sort this in order of
+ * frequency of use (but doesn't matter with only a few items
+ * anyhow)
+ */
+static const MessageHandler dbus_message_handlers[] = {
{ "Hello",
"",
DBUS_TYPE_STRING_AS_STRING,
{ "GetId",
"",
DBUS_TYPE_STRING_AS_STRING,
- bus_driver_handle_get_id }
+ bus_driver_handle_get_id },
+ { NULL, NULL, NULL, NULL }
+};
+
+static dbus_bool_t bus_driver_handle_introspect (DBusConnection *,
+ BusTransaction *, DBusMessage *, DBusError *);
+
+static const MessageHandler introspectable_message_handlers[] = {
+ { "Introspect", "", DBUS_TYPE_STRING_AS_STRING, bus_driver_handle_introspect },
+ { NULL, NULL, NULL, NULL }
+};
+
+#ifdef DBUS_ENABLE_STATS
+static const MessageHandler stats_message_handlers[] = {
+ { "GetStats", "", "a{sv}", bus_stats_handle_get_stats },
+ { "GetConnectionStats", "s", "a{sv}", bus_stats_handle_get_connection_stats },
+ { NULL, NULL, NULL, NULL }
+};
+#endif
+
+typedef struct {
+ const char *name;
+ const MessageHandler *message_handlers;
+ const char *extra_introspection;
+} InterfaceHandler;
+
+/* These should ideally be sorted by frequency of use, although it
+ * probably doesn't matter with this few items */
+static InterfaceHandler interface_handlers[] = {
+ { DBUS_INTERFACE_DBUS, dbus_message_handlers,
+ " <signal name=\"NameOwnerChanged\">\n"
+ " <arg type=\"s\"/>\n"
+ " <arg type=\"s\"/>\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NameLost\">\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n"
+ " <signal name=\"NameAcquired\">\n"
+ " <arg type=\"s\"/>\n"
+ " </signal>\n" },
+ { DBUS_INTERFACE_INTROSPECTABLE, introspectable_message_handlers, NULL },
+#ifdef DBUS_ENABLE_STATS
+ { BUS_INTERFACE_STATS, stats_message_handlers, NULL },
+#endif
+ { NULL, NULL, NULL }
};
static dbus_bool_t
dbus_bool_t
bus_driver_generate_introspect_string (DBusString *xml)
{
- int i;
+ const InterfaceHandler *ih;
+ const MessageHandler *mh;
if (!_dbus_string_append (xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE))
return FALSE;
if (!_dbus_string_append (xml, "<node>\n"))
return FALSE;
- if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE))
- return FALSE;
- if (!_dbus_string_append (xml, " <method name=\"Introspect\">\n"))
- return FALSE;
- if (!_dbus_string_append_printf (xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING))
- return FALSE;
- if (!_dbus_string_append (xml, " </method>\n"))
- return FALSE;
- if (!_dbus_string_append (xml, " </interface>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
- DBUS_INTERFACE_DBUS))
- return FALSE;
- i = 0;
- while (i < _DBUS_N_ELEMENTS (message_handlers))
+ for (ih = interface_handlers; ih->name != NULL; ih++)
{
-
- if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
- message_handlers[i].name))
+ if (!_dbus_string_append_printf (xml, " <interface name=\"%s\">\n",
+ ih->name))
return FALSE;
- if (!write_args_for_direction (xml, message_handlers[i].in_args, TRUE))
- return FALSE;
-
- if (!write_args_for_direction (xml, message_handlers[i].out_args, FALSE))
- return FALSE;
-
- if (!_dbus_string_append (xml, " </method>\n"))
- return FALSE;
-
- ++i;
- }
-
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameOwnerChanged\">\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
-
-
-
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameLost\">\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
-
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
-
+ for (mh = ih->message_handlers; mh->name != NULL; mh++)
+ {
+ if (!_dbus_string_append_printf (xml, " <method name=\"%s\">\n",
+ mh->name))
+ return FALSE;
+ if (!write_args_for_direction (xml, mh->in_args, TRUE))
+ return FALSE;
- if (!_dbus_string_append_printf (xml, " <signal name=\"NameAcquired\">\n"))
- return FALSE;
+ if (!write_args_for_direction (xml, mh->out_args, FALSE))
+ return FALSE;
- if (!_dbus_string_append_printf (xml, " <arg type=\"s\"/>\n"))
- return FALSE;
+ if (!_dbus_string_append (xml, " </method>\n"))
+ return FALSE;
+ }
- if (!_dbus_string_append_printf (xml, " </signal>\n"))
- return FALSE;
+ if (ih->extra_introspection != NULL &&
+ !_dbus_string_append (xml, ih->extra_introspection))
+ return FALSE;
- if (!_dbus_string_append (xml, " </interface>\n"))
- return FALSE;
+ if (!_dbus_string_append (xml, " </interface>\n"))
+ return FALSE;
+ }
if (!_dbus_string_append (xml, "</node>\n"))
return FALSE;
DBusMessage *message,
DBusError *error)
{
- const char *name, *sender, *interface;
- int i;
+ const char *name, *interface;
+ const InterfaceHandler *ih;
+ const MessageHandler *mh;
+ dbus_bool_t found_interface = FALSE;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
return TRUE; /* we just ignore this */
}
- if (dbus_message_is_method_call (message,
- DBUS_INTERFACE_INTROSPECTABLE,
- "Introspect"))
- return bus_driver_handle_introspect (connection, transaction, message, error);
-
+ /* may be NULL, which means "any interface will do" */
interface = dbus_message_get_interface (message);
- if (interface == NULL)
- interface = DBUS_INTERFACE_DBUS;
_dbus_assert (dbus_message_get_member (message) != NULL);
name = dbus_message_get_member (message);
- sender = dbus_message_get_sender (message);
- if (strcmp (interface,
- DBUS_INTERFACE_DBUS) != 0)
+ _dbus_verbose ("Driver got a method call: %s\n", name);
+
+ /* security checks should have kept this from getting here */
+#ifndef DBUS_DISABLE_ASSERT
{
- _dbus_verbose ("Driver got message to unknown interface \"%s\"\n",
- interface);
- goto unknown;
+ const char *sender = dbus_message_get_sender (message);
+
+ _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
}
+#endif
- _dbus_verbose ("Driver got a method call: %s\n",
- dbus_message_get_member (message));
+ for (ih = interface_handlers; ih->name != NULL; ih++)
+ {
+ if (interface != NULL && strcmp (interface, ih->name) != 0)
+ continue;
- /* security checks should have kept this from getting here */
- _dbus_assert (sender != NULL || strcmp (name, "Hello") == 0);
+ found_interface = TRUE;
- i = 0;
- while (i < _DBUS_N_ELEMENTS (message_handlers))
- {
- if (strcmp (message_handlers[i].name, name) == 0)
+ for (mh = ih->message_handlers; mh->name != NULL; mh++)
{
+ if (strcmp (mh->name, name) != 0)
+ continue;
+
_dbus_verbose ("Found driver handler for %s\n", name);
- if (!dbus_message_has_signature (message, message_handlers[i].in_args))
+ if (!dbus_message_has_signature (message, mh->in_args))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("Call to %s has wrong args (%s, expected %s)\n",
name, dbus_message_get_signature (message),
- message_handlers[i].in_args);
+ mh->in_args);
dbus_set_error (error, DBUS_ERROR_INVALID_ARGS,
"Call to %s has wrong args (%s, expected %s)\n",
name, dbus_message_get_signature (message),
- message_handlers[i].in_args);
+ mh->in_args);
_DBUS_ASSERT_ERROR_IS_SET (error);
return FALSE;
}
- if ((* message_handlers[i].handler) (connection, transaction, message, error))
+ if ((* mh->handler) (connection, transaction, message, error))
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
_dbus_verbose ("Driver handler succeeded\n");
return FALSE;
}
}
-
- ++i;
}
- unknown:
_dbus_verbose ("No driver handler for message \"%s\"\n",
name);
- dbus_set_error (error, DBUS_ERROR_UNKNOWN_METHOD,
+ dbus_set_error (error, found_interface ? DBUS_ERROR_UNKNOWN_METHOD : DBUS_ERROR_UNKNOWN_INTERFACE,
"%s does not understand message %s",
DBUS_SERVICE_DBUS, name);