LCOV - code coverage report
Current view: top level - sbus - sssd_dbus_signals.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 118 0.0 %
Date: 2016-06-29 Functions: 0 8 0.0 %

          Line data    Source code
       1             : /*
       2             :     Authors:
       3             :         Pavel Březina <pbrezina@redhat.com>
       4             : 
       5             :     Copyright (C) 2015 Red Hat
       6             : 
       7             :     This program is free software; you can redistribute it and/or modify
       8             :     it under the terms of the GNU General Public License as published by
       9             :     the Free Software Foundation; either version 3 of the License, or
      10             :     (at your option) any later version.
      11             : 
      12             :     This program is distributed in the hope that it will be useful,
      13             :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :     GNU General Public License for more details.
      16             : 
      17             :     You should have received a copy of the GNU General Public License
      18             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      19             : */
      20             : 
      21             : #include <talloc.h>
      22             : #include <dbus/dbus.h>
      23             : #include <dhash.h>
      24             : 
      25             : #include "util/util.h"
      26             : #include "sbus/sssd_dbus.h"
      27             : #include "sbus/sssd_dbus_private.h"
      28             : 
      29           0 : static int sbus_incoming_signal_destructor(struct sbus_incoming_signal *a_signal)
      30             : {
      31           0 :     dbus_message_unref(a_signal->message);
      32           0 :     return 0;
      33             : }
      34             : 
      35             : static struct sbus_incoming_signal *
      36           0 : sbus_new_incoming_signal(struct sbus_connection *conn,
      37             :                          DBusMessage *message)
      38             : {
      39             :     struct sbus_incoming_signal *a_signal;
      40             : 
      41           0 :     a_signal = talloc_zero(conn, struct sbus_incoming_signal);
      42           0 :     if (a_signal == NULL) {
      43           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Out of memory allocating D-Bus signal\n");
      44           0 :         return NULL;
      45             :     }
      46             : 
      47           0 :     a_signal->conn = conn;
      48           0 :     a_signal->message = dbus_message_ref(message);
      49           0 :     a_signal->interface = dbus_message_get_interface(message);
      50           0 :     a_signal->signal = dbus_message_get_member(message);
      51           0 :     a_signal->path = dbus_message_get_path(message);
      52             : 
      53           0 :     talloc_set_destructor(a_signal, sbus_incoming_signal_destructor);
      54             : 
      55           0 :     return a_signal;
      56             : }
      57             : 
      58             : struct sbus_incoming_signal_data {
      59             :     sbus_incoming_signal_fn handler_fn;
      60             :     void *handler_data;
      61             : };
      62             : 
      63             : errno_t
      64           0 : sbus_incoming_signal_hash_init(TALLOC_CTX *mem_ctx,
      65             :                                hash_table_t **_table)
      66             : {
      67           0 :     return sss_hash_create(mem_ctx, 10, _table);
      68             : }
      69             : 
      70             : static errno_t
      71           0 : sbus_incoming_signal_hash_add(hash_table_t *table,
      72             :                               const char *iface,
      73             :                               const char *a_signal,
      74             :                               sbus_incoming_signal_fn handler_fn,
      75             :                               void *handler_data)
      76             : {
      77             :     TALLOC_CTX *tmp_ctx;
      78             :     struct sbus_incoming_signal_data *data;
      79             :     hash_key_t key;
      80             :     hash_value_t value;
      81             :     errno_t ret;
      82             :     bool has_key;
      83             :     int hret;
      84             : 
      85           0 :     tmp_ctx = talloc_new(NULL);
      86           0 :     if (tmp_ctx == NULL) {
      87           0 :         return ENOMEM;
      88             :     }
      89             : 
      90           0 :     key.type = HASH_KEY_STRING;
      91           0 :     key.str = talloc_asprintf(tmp_ctx, "%s.%s", iface, a_signal);
      92           0 :     if (key.str == NULL) {
      93           0 :         ret = ENOMEM;
      94           0 :         goto done;
      95             :     }
      96             : 
      97           0 :     has_key = hash_has_key(table, &key);
      98           0 :     if (has_key) {
      99           0 :         ret = EEXIST;
     100           0 :         goto done;
     101             :     }
     102             : 
     103           0 :     data = talloc_zero(tmp_ctx, struct sbus_incoming_signal_data);
     104           0 :     if (data == NULL) {
     105           0 :         ret = ENOMEM;
     106           0 :         goto done;
     107             :     }
     108             : 
     109           0 :     data->handler_data = handler_data;
     110           0 :     data->handler_fn = handler_fn;
     111             : 
     112           0 :     value.type = HASH_VALUE_PTR;
     113           0 :     value.ptr = data;
     114             : 
     115           0 :     hret = hash_enter(table, &key, &value);
     116           0 :     if (hret != HASH_SUCCESS) {
     117           0 :         ret = EIO;
     118           0 :         goto done;
     119             :     }
     120             : 
     121           0 :     talloc_steal(table, key.str);
     122           0 :     talloc_steal(table, data);
     123             : 
     124           0 :     ret = EOK;
     125             : 
     126             : done:
     127           0 :     talloc_free(tmp_ctx);
     128           0 :     return ret;
     129             : }
     130             : 
     131             : static struct sbus_incoming_signal_data *
     132           0 : sbus_incoming_signal_hash_lookup(hash_table_t *table,
     133             :                                  const char *iface,
     134             :                                  const char *a_signal)
     135             : {
     136             :     struct sbus_incoming_signal_data *data;
     137             :     hash_key_t key;
     138             :     hash_value_t value;
     139             :     int hret;
     140             : 
     141           0 :     key.type = HASH_KEY_STRING;
     142           0 :     key.str = talloc_asprintf(NULL, "%s.%s", iface, a_signal);
     143           0 :     if (key.str == NULL) {
     144           0 :         return NULL;
     145             :     }
     146             : 
     147           0 :     hret = hash_lookup(table, &key, &value);
     148           0 :     if (hret == HASH_ERROR_KEY_NOT_FOUND) {
     149           0 :         data = NULL;
     150           0 :         goto done;
     151           0 :     } else if (hret != HASH_SUCCESS) {
     152           0 :         DEBUG(SSSDBG_OP_FAILURE,
     153             :               "Unable to search hash table: hret=%d\n", hret);
     154           0 :         data = NULL;
     155           0 :         goto done;
     156             :     }
     157             : 
     158           0 :     data = talloc_get_type(value.ptr, struct sbus_incoming_signal_data);
     159             : 
     160             : done:
     161           0 :     talloc_free(key.str);
     162           0 :     return data;
     163             : }
     164             : 
     165             : errno_t
     166           0 : sbus_signal_listen(struct sbus_connection *conn,
     167             :                    const char *iface,
     168             :                    const char *a_signal,
     169             :                    sbus_incoming_signal_fn handler_fn,
     170             :                    void *handler_data)
     171             : {
     172             :     TALLOC_CTX *tmp_ctx;
     173             :     const char *rule;
     174             :     DBusError error;
     175             :     errno_t ret;
     176             : 
     177           0 :     tmp_ctx = talloc_new(NULL);
     178           0 :     if (tmp_ctx == NULL) {
     179           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_new() failed\n");
     180           0 :         return ENOMEM;
     181             :     }
     182             : 
     183           0 :     dbus_error_init(&error);
     184             : 
     185           0 :     ret = sbus_incoming_signal_hash_add(conn->incoming_signals, iface,
     186             :                                         a_signal, handler_fn, handler_data);
     187           0 :     if (ret != EOK) {
     188           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Unable to register signal handler "
     189             :               "[%d]: %s\n", ret, sss_strerror(ret));
     190           0 :         goto done;
     191             :     }
     192             : 
     193           0 :     rule = talloc_asprintf(tmp_ctx, "type='signal',interface='%s',member='%s'",
     194             :                            iface, a_signal);
     195           0 :     if (rule == NULL) {
     196           0 :         ret = ENOMEM;
     197           0 :         goto done;
     198             :     }
     199             : 
     200           0 :     dbus_bus_add_match(conn->dbus.conn, rule, &error);
     201           0 :     if (dbus_error_is_set(&error)) {
     202           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     203             :               "Cannot add D-Bus match rule, cause: %s\n", error.message);
     204           0 :         ret = EIO;
     205           0 :         goto done;
     206             :     }
     207             : 
     208           0 :     DEBUG(SSSDBG_TRACE_FUNC, "Listening to signal %s.%s\n", iface, a_signal);
     209             : 
     210             : done:
     211           0 :     dbus_error_free(&error);
     212           0 :     talloc_free(tmp_ctx);
     213             : 
     214           0 :     return ret;
     215             : }
     216             : 
     217             : static void
     218             : sbus_signal_handler_got_caller_id(struct tevent_req *req);
     219             : 
     220             : DBusHandlerResult
     221           0 : sbus_signal_handler(DBusConnection *dbus_conn,
     222             :                     DBusMessage *message,
     223             :                     void *handler_data)
     224             : {
     225             :     struct tevent_req *req;
     226             :     struct sbus_connection *conn;
     227             :     struct sbus_incoming_signal *a_signal;
     228             :     const char *sender;
     229             :     int type;
     230             : 
     231           0 :     type = dbus_message_get_type(message);
     232           0 :     if (type != DBUS_MESSAGE_TYPE_SIGNAL) {
     233             :         /* We ignore other types here. */
     234           0 :         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     235             :     }
     236             : 
     237           0 :     conn = talloc_get_type(handler_data, struct sbus_connection);
     238           0 :     sender = dbus_message_get_sender(message);
     239             : 
     240             :     /* we have a valid handler, create D-Bus request */
     241           0 :     a_signal = sbus_new_incoming_signal(conn, message);
     242           0 :     if (a_signal == NULL) {
     243           0 :         return DBUS_HANDLER_RESULT_NEED_MEMORY;
     244             :     }
     245             : 
     246           0 :     DEBUG(SSSDBG_TRACE_INTERNAL, "Received D-Bus signal %s.%s\n",
     247             :           a_signal->interface, a_signal->signal);
     248             : 
     249             :     /* now get the sender ID */
     250           0 :     req = sbus_get_sender_id_send(a_signal, conn->ev, conn, sender);
     251           0 :     if (req == NULL) {
     252           0 :         talloc_free(a_signal);
     253           0 :         return DBUS_HANDLER_RESULT_NEED_MEMORY;
     254             :     }
     255           0 :     tevent_req_set_callback(req, sbus_signal_handler_got_caller_id, a_signal);
     256             : 
     257           0 :     return DBUS_HANDLER_RESULT_HANDLED;
     258             : }
     259             : 
     260             : static void
     261           0 : sbus_signal_handler_got_caller_id(struct tevent_req *req)
     262             : {
     263             :     struct sbus_incoming_signal_data *signal_data;
     264             :     struct sbus_incoming_signal *a_signal;
     265             :     errno_t ret;
     266             : 
     267           0 :     a_signal = tevent_req_callback_data(req, struct sbus_incoming_signal);
     268             : 
     269           0 :     ret = sbus_get_sender_id_recv(req, &a_signal->client);
     270           0 :     if (ret == ERR_SBUS_SENDER_BUS) {
     271           0 :         DEBUG(SSSDBG_TRACE_FUNC, "Got a signal from the bus..\n");
     272           0 :     } else if (ret != EOK) {
     273           0 :         DEBUG(SSSDBG_CRIT_FAILURE,
     274             :               "Failed to resolve caller's ID: %s\n", sss_strerror(ret));
     275           0 :         goto done;
     276             :     }
     277             : 
     278           0 :     signal_data = sbus_incoming_signal_hash_lookup(
     279           0 :                                             a_signal->conn->incoming_signals,
     280             :                                             a_signal->interface,
     281             :                                             a_signal->signal);
     282           0 :     if (signal_data == NULL) {
     283           0 :         DEBUG(SSSDBG_MINOR_FAILURE, "Received signal %s.%s that we are "
     284             :               "not listening to.\n", a_signal->interface, a_signal->signal);
     285           0 :         goto done;
     286             :     }
     287             : 
     288           0 :     signal_data->handler_fn(a_signal, signal_data->handler_data);
     289             : 
     290             : done:
     291           0 :     talloc_free(a_signal);
     292           0 : }

Generated by: LCOV version 1.10