Line data Source code
1 : /*
2 : Authors:
3 : Pavel Březina <pbrezina@redhat.com>
4 :
5 : Copyright (C) 2014 Red Hat
6 :
7 : SBUS: Interface introspection
8 :
9 : This program is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3 of the License, or
12 : (at your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful,
15 : but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : GNU General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program. If not, see <http://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "config.h"
24 :
25 : #include <dbus/dbus.h>
26 : #include <errno.h>
27 :
28 : #include "util/util.h"
29 : #include "sbus/sssd_dbus.h"
30 : #include "sbus/sssd_dbus_meta.h"
31 : #include "sbus/sssd_dbus_private.h"
32 : #include "sbus/sssd_dbus_invokers.h"
33 :
34 : static int
35 0 : sbus_invoke_get_basic(struct sbus_request *sbus_req,
36 : void *function_ptr,
37 : void *value_ptr,
38 : int dbus_type,
39 : DBusMessageIter *iter)
40 : {
41 : void (*handler_fn)(struct sbus_request *, void *, void *);
42 : dbus_bool_t value_bool;
43 : dbus_bool_t dbret;
44 :
45 0 : handler_fn = function_ptr;
46 0 : handler_fn(sbus_req, sbus_req->intf->handler_data, value_ptr);
47 :
48 0 : if (dbus_type == DBUS_TYPE_BOOLEAN) {
49 : /* Special case to convert bool into dbus_bool_t. */
50 0 : value_bool = *((bool *) value_ptr);
51 0 : value_ptr = &value_bool;
52 : }
53 :
54 0 : dbret = dbus_message_iter_append_basic(iter, dbus_type, value_ptr);
55 0 : return dbret ? EOK : EIO;
56 : }
57 :
58 : static int
59 0 : sbus_invoke_get_string(struct sbus_request *sbus_req,
60 : void *function_ptr,
61 : const char *default_value,
62 : int dbus_type,
63 : DBusMessageIter *iter)
64 : {
65 : void (*handler_fn)(struct sbus_request *, void *, const char **);
66 0 : const char *value = NULL;
67 : dbus_bool_t dbret;
68 :
69 0 : handler_fn = function_ptr;
70 0 : handler_fn(sbus_req, sbus_req->intf->handler_data, &value);
71 :
72 0 : value = value == NULL ? default_value : value;
73 :
74 0 : dbret = dbus_message_iter_append_basic(iter, dbus_type, &value);
75 0 : return dbret ? EOK : EIO;
76 : }
77 :
78 : static int
79 0 : sbus_invoke_get_array(struct sbus_request *sbus_req,
80 : void *function_ptr,
81 : unsigned int item_size,
82 : int dbus_type,
83 : DBusMessageIter *iter)
84 : {
85 : void (*handler_fn)(struct sbus_request *, void *, void *, int *);
86 0 : const char array_type[2] = {dbus_type, '\0'};
87 : DBusMessageIter array;
88 : dbus_bool_t dbret;
89 : uint8_t *values;
90 : void *addr;
91 : int num_values;
92 : int i;
93 :
94 0 : handler_fn = function_ptr;
95 0 : handler_fn(sbus_req, sbus_req->intf->handler_data, &values, &num_values);
96 :
97 0 : dbret = dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
98 : array_type, &array);
99 0 : if (!dbret) {
100 0 : return EIO;
101 : }
102 :
103 0 : for (i = 0; i < num_values; i++) {
104 0 : addr = values + i * item_size;
105 :
106 0 : dbret = dbus_message_iter_append_basic(&array, dbus_type, addr);
107 0 : if (!dbret) {
108 0 : return ENOMEM;
109 : }
110 : }
111 :
112 0 : dbret = dbus_message_iter_close_container(iter, &array);
113 0 : if (!dbret) {
114 0 : return EIO;
115 : }
116 :
117 0 : return EOK;
118 : }
119 :
120 0 : int sbus_invoke_get_y(DBusMessageIter *iter,
121 : struct sbus_request *sbus_req,
122 : void *function_ptr)
123 : {
124 : uint8_t value;
125 :
126 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
127 : DBUS_TYPE_BYTE, iter);
128 : }
129 :
130 0 : int sbus_invoke_get_b(DBusMessageIter *iter,
131 : struct sbus_request *sbus_req,
132 : void *function_ptr)
133 : {
134 : bool value;
135 :
136 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
137 : DBUS_TYPE_BOOLEAN, iter);
138 : }
139 :
140 0 : int sbus_invoke_get_n(DBusMessageIter *iter,
141 : struct sbus_request *sbus_req,
142 : void *function_ptr)
143 : {
144 : int16_t value;
145 :
146 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
147 : DBUS_TYPE_INT16, iter);
148 : }
149 :
150 0 : int sbus_invoke_get_q(DBusMessageIter *iter,
151 : struct sbus_request *sbus_req,
152 : void *function_ptr)
153 : {
154 : uint16_t value;
155 :
156 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
157 : DBUS_TYPE_UINT16, iter);
158 : }
159 :
160 0 : int sbus_invoke_get_i(DBusMessageIter *iter,
161 : struct sbus_request *sbus_req,
162 : void *function_ptr)
163 : {
164 : int32_t value;
165 :
166 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
167 : DBUS_TYPE_INT32, iter);
168 : }
169 :
170 0 : int sbus_invoke_get_u(DBusMessageIter *iter,
171 : struct sbus_request *sbus_req,
172 : void *function_ptr)
173 : {
174 : uint32_t value;
175 :
176 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
177 : DBUS_TYPE_UINT32, iter);
178 : }
179 :
180 0 : int sbus_invoke_get_x(DBusMessageIter *iter,
181 : struct sbus_request *sbus_req,
182 : void *function_ptr)
183 : {
184 : int64_t value;
185 :
186 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
187 : DBUS_TYPE_INT64, iter);
188 : }
189 :
190 0 : int sbus_invoke_get_t(DBusMessageIter *iter,
191 : struct sbus_request *sbus_req,
192 : void *function_ptr)
193 : {
194 : uint64_t value;
195 :
196 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
197 : DBUS_TYPE_UINT64, iter);
198 : }
199 :
200 0 : int sbus_invoke_get_d(DBusMessageIter *iter,
201 : struct sbus_request *sbus_req,
202 : void *function_ptr)
203 : {
204 : double value;
205 :
206 0 : return sbus_invoke_get_basic(sbus_req, function_ptr, &value,
207 : DBUS_TYPE_DOUBLE, iter);
208 : }
209 :
210 0 : int sbus_invoke_get_s(DBusMessageIter *iter,
211 : struct sbus_request *sbus_req,
212 : void *function_ptr)
213 : {
214 0 : return sbus_invoke_get_string(sbus_req, function_ptr, "",
215 : DBUS_TYPE_STRING, iter);
216 : }
217 :
218 0 : int sbus_invoke_get_o(DBusMessageIter *iter,
219 : struct sbus_request *sbus_req,
220 : void *function_ptr)
221 : {
222 0 : return sbus_invoke_get_string(sbus_req, function_ptr, "/",
223 : DBUS_TYPE_OBJECT_PATH, iter);
224 : }
225 :
226 0 : int sbus_invoke_get_ay(DBusMessageIter *iter,
227 : struct sbus_request *sbus_req,
228 : void *function_ptr)
229 : {
230 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint8_t),
231 : DBUS_TYPE_BYTE, iter);
232 : }
233 :
234 0 : int sbus_invoke_get_an(DBusMessageIter *iter,
235 : struct sbus_request *sbus_req,
236 : void *function_ptr)
237 : {
238 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(int16_t),
239 : DBUS_TYPE_INT16, iter);
240 : }
241 :
242 0 : int sbus_invoke_get_aq(DBusMessageIter *iter,
243 : struct sbus_request *sbus_req,
244 : void *function_ptr)
245 : {
246 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint16_t),
247 : DBUS_TYPE_UINT16, iter);
248 : }
249 :
250 0 : int sbus_invoke_get_ai(DBusMessageIter *iter,
251 : struct sbus_request *sbus_req,
252 : void *function_ptr)
253 : {
254 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(int32_t),
255 : DBUS_TYPE_INT32, iter);
256 : }
257 :
258 0 : int sbus_invoke_get_au(DBusMessageIter *iter,
259 : struct sbus_request *sbus_req,
260 : void *function_ptr)
261 : {
262 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint32_t),
263 : DBUS_TYPE_UINT32, iter);
264 : }
265 :
266 0 : int sbus_invoke_get_ax(DBusMessageIter *iter,
267 : struct sbus_request *sbus_req,
268 : void *function_ptr)
269 : {
270 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(int64_t),
271 : DBUS_TYPE_INT64, iter);
272 : }
273 :
274 0 : int sbus_invoke_get_at(DBusMessageIter *iter,
275 : struct sbus_request *sbus_req,
276 : void *function_ptr)
277 : {
278 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(uint64_t),
279 : DBUS_TYPE_UINT64, iter);
280 : }
281 :
282 0 : int sbus_invoke_get_ad(DBusMessageIter *iter,
283 : struct sbus_request *sbus_req,
284 : void *function_ptr)
285 : {
286 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(double),
287 : DBUS_TYPE_DOUBLE, iter);
288 : }
289 :
290 0 : int sbus_invoke_get_as(DBusMessageIter *iter,
291 : struct sbus_request *sbus_req,
292 : void *function_ptr)
293 : {
294 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(const char *),
295 : DBUS_TYPE_STRING, iter);
296 : }
297 :
298 0 : int sbus_invoke_get_ao(DBusMessageIter *iter,
299 : struct sbus_request *sbus_req,
300 : void *function_ptr)
301 : {
302 0 : return sbus_invoke_get_array(sbus_req, function_ptr, sizeof(const char *),
303 : DBUS_TYPE_OBJECT_PATH, iter);
304 : }
305 :
306 0 : int sbus_invoke_get_aDOsasDE(DBusMessageIter *iter,
307 : struct sbus_request *sbus_req,
308 : void *function_ptr)
309 : {
310 : void (*handler_fn)(struct sbus_request *, void *, hash_table_t **);
311 : DBusMessageIter it_array;
312 : DBusMessageIter it_dict;
313 : DBusMessageIter it_values;
314 : hash_table_t *table;
315 0 : struct hash_iter_context_t *table_iter = NULL;
316 : hash_entry_t *entry;
317 : const char **values;
318 : dbus_bool_t dbret;
319 : errno_t ret;
320 : int i;
321 :
322 0 : handler_fn = function_ptr;
323 0 : handler_fn(sbus_req, sbus_req->intf->handler_data, &table);
324 :
325 0 : dbret = dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY,
326 : DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
327 : DBUS_TYPE_STRING_AS_STRING
328 : DBUS_TYPE_ARRAY_AS_STRING
329 : DBUS_TYPE_STRING_AS_STRING
330 : DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &it_array);
331 0 : if (!dbret) {
332 0 : ret = EIO;
333 0 : goto done;
334 : }
335 :
336 : /* iterate over keys */
337 :
338 0 : if (table == NULL) {
339 0 : dbret = dbus_message_iter_close_container(iter, &it_array);
340 0 : if (!dbret) {
341 0 : ret = EIO;
342 0 : goto done;
343 : }
344 :
345 0 : ret = EOK;
346 0 : goto done;
347 : }
348 :
349 0 : table_iter = new_hash_iter_context(table);
350 0 : while ((entry = table_iter->next(table_iter)) != NULL) {
351 0 : if (entry->key.type != HASH_KEY_STRING || entry->key.str == NULL
352 0 : || entry->value.type != HASH_VALUE_PTR
353 0 : || entry->value.ptr == NULL) {
354 0 : continue;
355 : }
356 :
357 0 : dbret = dbus_message_iter_open_container(&it_array,
358 : DBUS_TYPE_DICT_ENTRY, NULL,
359 : &it_dict);
360 0 : if (!dbret) {
361 0 : ret = EIO;
362 0 : goto done;
363 : }
364 :
365 : /* append key as dict entry key */
366 :
367 0 : dbret = dbus_message_iter_append_basic(&it_dict,
368 : DBUS_TYPE_STRING,
369 0 : &entry->key.str);
370 0 : if (!dbret) {
371 0 : ret = EIO;
372 0 : goto done;
373 : }
374 :
375 : /* iterate over values */
376 :
377 0 : dbret = dbus_message_iter_open_container(&it_dict,
378 : DBUS_TYPE_ARRAY,
379 : DBUS_TYPE_STRING_AS_STRING,
380 : &it_values);
381 0 : if (!dbret) {
382 0 : ret = EIO;
383 0 : goto done;
384 : }
385 :
386 0 : values = entry->value.ptr;
387 0 : for (i = 0; values[i] != NULL; i++) {
388 : /* append value into array */
389 0 : dbret = dbus_message_iter_append_basic(&it_values,
390 : DBUS_TYPE_STRING,
391 0 : &values[i]);
392 0 : if (!dbret) {
393 0 : ret = EIO;
394 0 : goto done;
395 : }
396 : }
397 :
398 0 : dbret = dbus_message_iter_close_container(&it_dict, &it_values);
399 0 : if (!dbret) {
400 0 : ret = EIO;
401 0 : goto done;
402 : }
403 :
404 0 : dbret = dbus_message_iter_close_container(&it_array, &it_dict);
405 0 : if (!dbret) {
406 0 : ret = EIO;
407 0 : goto done;
408 : }
409 : }
410 :
411 0 : dbret = dbus_message_iter_close_container(iter, &it_array);
412 0 : if (!dbret) {
413 0 : ret = EIO;
414 0 : goto done;
415 : }
416 :
417 0 : ret = EOK;
418 :
419 : done:
420 0 : talloc_free(table_iter);
421 0 : return ret;
422 : }
423 :
424 0 : void sbus_invoke_get(struct sbus_request *sbus_req,
425 : const char *type,
426 : sbus_get_invoker_fn invoker_fn,
427 : sbus_msg_handler_fn handler_fn)
428 : {
429 0 : DBusMessage *reply = NULL;
430 : DBusMessageIter iter;
431 : DBusMessageIter variant;
432 : dbus_bool_t dbret;
433 : errno_t ret;
434 :
435 0 : reply = dbus_message_new_method_return(sbus_req->message);
436 0 : if (reply == NULL) {
437 0 : ret = ENOMEM;
438 0 : goto fail;
439 : }
440 :
441 0 : dbus_message_iter_init_append(reply, &iter);
442 :
443 0 : dbret = dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
444 : type, &variant);
445 0 : if (!dbret) {
446 0 : ret = ENOMEM;
447 0 : goto fail;
448 : }
449 :
450 0 : ret = invoker_fn(&variant, sbus_req, handler_fn);
451 0 : if (ret != EOK) {
452 0 : DEBUG(SSSDBG_CRIT_FAILURE,
453 : "Invoker error [%d]: %s\n", ret, sss_strerror(ret));
454 0 : goto fail;
455 : }
456 :
457 0 : dbret = dbus_message_iter_close_container(&iter, &variant);
458 0 : if (!dbret) {
459 0 : ret = EIO;
460 0 : goto fail;
461 : }
462 :
463 0 : sbus_request_finish(sbus_req, reply);
464 0 : return;
465 :
466 : fail:
467 0 : DEBUG(SSSDBG_CRIT_FAILURE,
468 : "Unable to reply [%d]: %s\n", ret, sss_strerror(ret));
469 :
470 0 : if (reply != NULL) {
471 0 : dbus_message_unref(reply);
472 : }
473 0 : sbus_request_finish(sbus_req, NULL);
474 :
475 0 : return;
476 : }
477 :
478 0 : void sbus_invoke_get_all(struct sbus_request *sbus_req)
479 : {
480 : const struct sbus_property_meta *props;
481 : sbus_msg_handler_fn *handler_fn;
482 0 : DBusMessage *reply = NULL;
483 : DBusMessageIter iter;
484 : DBusMessageIter array;
485 : DBusMessageIter dict;
486 : DBusMessageIter variant;
487 : dbus_bool_t dbret;
488 : errno_t ret;
489 : int i;
490 :
491 0 : reply = dbus_message_new_method_return(sbus_req->message);
492 0 : if (reply == NULL) {
493 0 : ret = ENOMEM;
494 0 : goto fail;
495 : }
496 :
497 0 : dbus_message_iter_init_append(reply, &iter);
498 :
499 0 : dbret = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
500 : DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
501 : DBUS_TYPE_STRING_AS_STRING
502 : DBUS_TYPE_VARIANT_AS_STRING
503 : DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
504 : &array);
505 0 : if (!dbret) {
506 0 : ret = ENOMEM;
507 0 : goto fail;
508 : }
509 :
510 0 : props = sbus_req->intf->vtable->meta->properties;
511 :
512 0 : if (props != NULL) {
513 0 : for (i = 0; props[i].name != NULL; i++) {
514 0 : dbret = dbus_message_iter_open_container(&array,
515 : DBUS_TYPE_DICT_ENTRY, NULL,
516 : &dict);
517 0 : if (!dbret) {
518 0 : ret = ENOMEM;
519 0 : goto fail;
520 : }
521 :
522 : /* key */
523 0 : dbret = dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING,
524 0 : &props[i].name);
525 0 : if (!dbret) {
526 0 : ret = ENOMEM;
527 0 : goto fail;
528 : }
529 :
530 : /* value */
531 0 : dbret = dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT,
532 0 : props[i].type, &variant);
533 0 : if (!dbret) {
534 0 : ret = ENOMEM;
535 0 : goto fail;
536 : }
537 :
538 0 : handler_fn = VTABLE_FUNC(sbus_req->intf->vtable,
539 : props[i].vtable_offset_get);
540 0 : if (handler_fn == NULL) {
541 0 : ret = ERR_INTERNAL;
542 0 : goto fail;
543 : }
544 :
545 0 : ret = props[i].invoker_get(&variant, sbus_req, handler_fn);
546 0 : if (ret != EOK) {
547 0 : DEBUG(SSSDBG_CRIT_FAILURE,
548 : "Invoker error [%d]: %s\n", ret, sss_strerror(ret));
549 0 : goto fail;
550 : }
551 :
552 0 : dbret = dbus_message_iter_close_container(&dict, &variant);
553 0 : if (!dbret) {
554 0 : ret = EIO;
555 0 : goto fail;
556 : }
557 :
558 0 : dbret = dbus_message_iter_close_container(&array, &dict);
559 0 : if (!dbret) {
560 0 : ret = EIO;
561 0 : goto fail;
562 : }
563 : }
564 : }
565 :
566 0 : dbret = dbus_message_iter_close_container(&iter, &array);
567 0 : if (!dbret) {
568 0 : ret = EIO;
569 0 : goto fail;
570 : }
571 :
572 0 : sbus_request_finish(sbus_req, reply);
573 0 : return;
574 :
575 : fail:
576 0 : DEBUG(SSSDBG_CRIT_FAILURE,
577 : "Unable to reply [%d]: %s\n", ret, sss_strerror(ret));
578 :
579 0 : dbus_message_unref(reply);
580 0 : sbus_request_finish(sbus_req, NULL);
581 :
582 0 : return;
583 : }
|