diff options
Diffstat (limited to 'bus/connection.c')
-rw-r--r-- | bus/connection.c | 152 |
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; +} |