summaryrefslogtreecommitdiff
path: root/bus/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'bus/connection.c')
-rw-r--r--bus/connection.c152
1 files changed, 150 insertions, 2 deletions
diff --git a/bus/connection.c b/bus/connection.c
index d69758c9..2d68c84e 100644
--- a/bus/connection.c
+++ b/bus/connection.c
@@ -30,9 +30,16 @@
#include "signals.h"
#include "expirelist.h"
#include "selinux.h"
+#include "driver-afbus.h"
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-timeout.h>
+#ifdef HAVE_AFBUS
+#include <dbus/dbus-transport-afbus.h>
+#endif
+
+#include <sys/types.h> /* See NOTES */
+#include <sys/socket.h>
/* Trim executed commands to this length; we want to keep logs readable */
#define MAX_LOG_COMMAND_LEN 50
@@ -94,6 +101,13 @@ typedef struct
char *cached_loginfo_string;
BusSELinuxID *selinux_id;
+ dbus_bool_t peer_address_set;
+ struct sockaddr_storage peer_address;
+ socklen_t peer_addrlen;
+ DBusConnection *proxy_connection; /**< If this is a compat connection,
+ proxy_connection is the proxy
+ connection to AF_BUS */
+
long connection_tv_sec; /**< Time when we connected (seconds component) */
long connection_tv_usec; /**< Time when we connected (microsec component) */
int stamp; /**< connections->stamp last time we were traversed */
@@ -184,12 +198,33 @@ adjust_connections_for_uid (BusConnections *connections,
}
}
+static DBusHandlerResult
+proxy_connection_message_filter (DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data)
+{
+ DBusConnection *source_connection = user_data;
+
+ if (dbus_message_get_destination (message) == NULL &&
+ dbus_message_is_signal (message,
+ DBUS_INTERFACE_LOCAL,
+ "Disconnected"))
+ {
+ dbus_connection_close (source_connection);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ dbus_connection_send (source_connection, message, NULL);
+ return DBUS_HANDLER_RESULT_HANDLED;
+}
+
void
bus_connection_disconnected (DBusConnection *connection)
{
BusConnectionData *d;
BusService *service;
BusMatchmaker *matchmaker;
+ DBusError error;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
@@ -197,6 +232,20 @@ bus_connection_disconnected (DBusConnection *connection)
_dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
d->name ? d->name : "(inactive)");
+ if (d->proxy_connection)
+ {
+ dbus_connection_remove_filter (d->proxy_connection,
+ proxy_connection_message_filter, connection);
+ dbus_connection_close (d->proxy_connection);
+ dbus_connection_unref (d->proxy_connection);
+ d->proxy_connection = NULL;
+ }
+
+ dbus_error_init (&error);
+
+ if (!bus_driver_afbus_disconnected(connection, &error))
+ dbus_error_free (&error);
+
/* Delete our match rules */
if (d->n_match_rules > 0)
{
@@ -309,6 +358,18 @@ bus_connection_disconnected (DBusConnection *connection)
dbus_connection_unref (connection);
}
+DBusConnection *
+bus_connection_get_proxy_connection (DBusConnection *connection)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+
+ _dbus_assert (d != NULL);
+
+ return d->proxy_connection;
+}
+
static dbus_bool_t
add_connection_watch (DBusWatch *watch,
void *data)
@@ -588,6 +649,52 @@ oom:
return FALSE;
}
+#ifdef HAVE_AFBUS
+static dbus_bool_t
+bus_connections_setup_proxy_connection (BusConnections *connections,
+ DBusConnection *connection,
+ const char *main_address)
+{
+ BusConnectionData *d = BUS_CONNECTION_DATA (connection);
+ DBusError error;
+ dbus_bool_t retval = FALSE;
+
+ dbus_error_init (&error);
+
+ d->proxy_connection
+ = dbus_connection_open_private (main_address, &error);
+ if (dbus_error_is_set (&error))
+ {
+ dbus_error_free (&error);
+ goto out;
+ }
+
+ dbus_connection_set_route_peer_messages (d->proxy_connection, TRUE);
+
+ dbus_connection_set_dispatch_status_function (d->proxy_connection,
+ dispatch_status_function,
+ bus_context_get_loop (connections->context), NULL);
+
+ if (!dbus_connection_add_filter(d->proxy_connection,
+ proxy_connection_message_filter, connection, NULL))
+ goto out;
+
+
+ if (!dbus_connection_set_watch_functions (d->proxy_connection,
+ add_connection_watch,
+ remove_connection_watch,
+ toggle_connection_watch,
+ connection,
+ NULL))
+ goto out;
+
+ return TRUE;
+
+out:
+ return retval;
+}
+#endif
+
dbus_bool_t
bus_connections_setup_connection (BusConnections *connections,
DBusConnection *connection)
@@ -596,7 +703,6 @@ bus_connections_setup_connection (BusConnections *connections,
BusConnectionData *d;
dbus_bool_t retval;
DBusError error;
-
d = dbus_new0 (BusConnectionData, 1);
@@ -622,8 +728,32 @@ bus_connections_setup_connection (BusConnections *connections,
dbus_connection_set_route_peer_messages (connection, TRUE);
retval = FALSE;
-
dbus_error_init (&error);
+
+#ifdef HAVE_AFBUS
+ d->peer_addrlen = sizeof(d->peer_address);
+ d->peer_address_set = dbus_connection_get_peer_address (connection,
+ &d->peer_address, (long int *)&d->peer_addrlen);
+
+ /* If this connection is not AF_BUS, and we have a AF_BUS
+ * server, we are in compat mode and we need to setup a
+ * new connection */
+ if (d->peer_address_set &&
+ ((struct sockaddr *)&d->peer_address)->sa_family != AF_BUS)
+ {
+ const char *main_address;
+ main_address = bus_context_get_main_address (connections->context);
+ if (main_address && main_address[0] != '\0')
+ {
+ if (!bus_connections_setup_proxy_connection (connections, connection,
+ main_address))
+ {
+ goto out;
+ }
+ }
+ }
+#endif
+
d->selinux_id = bus_selinux_init_connection_id (connection,
&error);
if (dbus_error_is_set (&error))
@@ -2383,3 +2513,21 @@ bus_connection_get_peak_bus_names (DBusConnection *connection)
return d->peak_bus_names;
}
#endif /* DBUS_ENABLE_STATS */
+
+int
+bus_connection_get_peer_address (DBusConnection *connection,
+ struct sockaddr **peer_address,
+ socklen_t *peer_addrlen)
+{
+ BusConnectionData *d;
+
+ d = BUS_CONNECTION_DATA (connection);
+
+ if (!d->peer_address_set)
+ return FALSE;
+
+ *peer_address = (struct sockaddr *) &d->peer_address;
+ *peer_addrlen = d->peer_addrlen;
+
+ return TRUE;
+}