summaryrefslogtreecommitdiffstats
path: root/src/sbus/sssd_dbus_properties.c
blob: 835b3078b5abd124ab98265401aa48533a306ee3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/*
    Authors:
        Stef Walter <stefw@redhat.com>

    Copyright (C) 2014 Red Hat

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "util/util.h"
#include "sbus/sssd_dbus.h"
#include "sbus/sssd_dbus_meta.h"
#include "sbus/sssd_dbus_private.h"

static int
dispatch_properties_set(struct sbus_connection *conn,
                        struct sbus_interface *intf,
                        DBusMessage *message)
{
    const char *signature;
    const struct sbus_interface_meta *meta;
    const struct sbus_property_meta *property;
    const char *interface_name;
    const char *property_name;
    const char *type;
    struct sbus_request *req;
    sbus_msg_handler_fn handler_fn;
    DBusMessageIter iter;
    DBusMessageIter variant;

    req = sbus_new_request(conn, intf, message);
    if (!req)
        return ENOMEM;

    meta = intf->vtable->meta;

    signature = dbus_message_get_signature(message);
    if (strcmp (signature, "ssv") != 0) {
        return sbus_request_fail_and_finish(req,
                    sbus_error_new(req,
                                   DBUS_ERROR_INVALID_ARGS,
                                   "Invalid argument types passed " \
                                   "to Set method"));
    }

    dbus_message_iter_init (message, &iter);
    dbus_message_iter_get_basic (&iter, &interface_name);
    dbus_message_iter_next (&iter);
    dbus_message_iter_get_basic (&iter, &property_name);
    dbus_message_iter_next (&iter);

    if (strcmp (interface_name, meta->name) != 0) {
        return sbus_request_fail_and_finish(req,
                    sbus_error_new(req,
                                   DBUS_ERROR_UNKNOWN_INTERFACE,
                                   "No such interface"));
    }

    property = sbus_meta_find_property (intf->vtable->meta, property_name);
    if (property == NULL) {
        return sbus_request_fail_and_finish(req,
                    sbus_error_new(req,
                                   DBUS_ERROR_UNKNOWN_PROPERTY,
                                   "No such property"));
    }

    if (!(property->flags & SBUS_PROPERTY_WRITABLE)) {
        return sbus_request_fail_and_finish(req,
                    sbus_error_new(req,
                                   DBUS_ERROR_PROPERTY_READ_ONLY,
                                   "Property is not writable"));
    }

    dbus_message_iter_recurse(&iter, &variant);
    type = dbus_message_iter_get_signature (&variant);
    if (strcmp (property->type, type) != 0) {
        return sbus_request_fail_and_finish(req,
                    sbus_error_new(req,
                                   DBUS_ERROR_INVALID_ARGS,
                                   "Invalid data type for property"));
    }

    handler_fn = VTABLE_FUNC(intf->vtable, property->vtable_offset_set);
    if (!handler_fn) {
        return sbus_request_fail_and_finish(req,
                    sbus_error_new(req,
                                   DBUS_ERROR_NOT_SUPPORTED,
                                   "Not implemented"));
    }

    sbus_request_invoke_or_finish(req, handler_fn,
                                  intf->instance_data,
                                  property->invoker_set);
    return EOK;
}

int sbus_properties_dispatch(struct sbus_request *dbus_req)
{
    const char *member;

    member = dbus_message_get_member(dbus_req->message);

    /* Set is handled a lot like a method invocation */
    if (strcmp(member, "Set") == 0) {
        return dispatch_properties_set(dbus_req->conn,
                                       dbus_req->intf,
                                       dbus_req->message);
    }

    return ERR_SBUS_NOSUP;
}