]> git.meshlink.io Git - catta/blob - avahi-daemon/dbus-util.c
get rid of a lot of old svn cruft
[catta] / avahi-daemon / dbus-util.c
1 /***
2   This file is part of avahi.
3
4   avahi is free software; you can redistribute it and/or modify it
5   under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2.1 of the
7   License, or (at your option) any later version.
8
9   avahi is distributed in the hope that it will be useful, but WITHOUT
10   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12   Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with avahi; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17   USA.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <errno.h>
30 #include <string.h>
31
32 #include <avahi-common/error.h>
33 #include <avahi-common/dbus.h>
34 #include <avahi-common/malloc.h>
35 #include <avahi-core/log.h>
36 #include <avahi-core/core.h>
37
38 #ifdef ENABLE_CHROOT
39 #include "chroot.h"
40 #endif
41
42 #include "main.h"
43 #include "dbus-util.h"
44
45 DBusHandlerResult avahi_dbus_respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
46     DBusMessage *reply;
47
48     assert(-error > -AVAHI_OK);
49     assert(-error < -AVAHI_ERR_MAX);
50
51     if (!text)
52         text = avahi_strerror(error);
53
54     reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
55     dbus_connection_send(c, reply, NULL);
56     dbus_message_unref(reply);
57
58     avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
59
60     return DBUS_HANDLER_RESULT_HANDLED;
61 }
62
63 DBusHandlerResult avahi_dbus_respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
64     DBusMessage *reply;
65
66     reply = dbus_message_new_method_return(m);
67     dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
68     dbus_connection_send(c, reply, NULL);
69     dbus_message_unref(reply);
70
71     return DBUS_HANDLER_RESULT_HANDLED;
72 }
73
74 DBusHandlerResult avahi_dbus_respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
75     DBusMessage *reply;
76
77     reply = dbus_message_new_method_return(m);
78     dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
79     dbus_connection_send(c, reply, NULL);
80     dbus_message_unref(reply);
81
82     return DBUS_HANDLER_RESULT_HANDLED;
83 }
84
85 DBusHandlerResult avahi_dbus_respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
86     DBusMessage *reply;
87
88     reply = dbus_message_new_method_return(m);
89     dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
90     dbus_connection_send(c, reply, NULL);
91     dbus_message_unref(reply);
92
93     return DBUS_HANDLER_RESULT_HANDLED;
94 }
95
96 DBusHandlerResult avahi_dbus_respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
97     DBusMessage *reply;
98
99     reply = dbus_message_new_method_return(m);
100     dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
101     dbus_connection_send(c, reply, NULL);
102     dbus_message_unref(reply);
103
104     return DBUS_HANDLER_RESULT_HANDLED;
105 }
106
107 DBusHandlerResult avahi_dbus_respond_ok(DBusConnection *c, DBusMessage *m) {
108     DBusMessage *reply;
109
110     reply = dbus_message_new_method_return(m);
111     dbus_connection_send(c, reply, NULL);
112     dbus_message_unref(reply);
113
114     return DBUS_HANDLER_RESULT_HANDLED;
115 }
116
117 DBusHandlerResult avahi_dbus_respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
118     DBusMessage *reply;
119
120     reply = dbus_message_new_method_return(m);
121     dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
122     dbus_connection_send(c, reply, NULL);
123     dbus_message_unref(reply);
124
125     return DBUS_HANDLER_RESULT_HANDLED;
126 }
127
128 void avahi_dbus_append_server_error(DBusMessage *reply) {
129     const char *t;
130
131     t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
132
133     dbus_message_append_args(
134         reply,
135         DBUS_TYPE_STRING, &t,
136         DBUS_TYPE_INVALID);
137 }
138
139 const char *avahi_dbus_map_browse_signal_name(AvahiBrowserEvent e) {
140     switch (e) {
141         case AVAHI_BROWSER_NEW : return "ItemNew";
142         case AVAHI_BROWSER_REMOVE : return "ItemRemove";
143         case AVAHI_BROWSER_FAILURE : return "Failure";
144         case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
145         case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
146     }
147
148     abort();
149 }
150
151 const char *avahi_dbus_map_resolve_signal_name(AvahiResolverEvent e) {
152     switch (e) {
153         case AVAHI_RESOLVER_FOUND : return "Found";
154         case AVAHI_RESOLVER_FAILURE : return "Failure";
155     }
156
157     abort();
158 }
159
160 static char *file_get_contents(const char *fname) {
161     int fd = -1;
162     struct stat st;
163     ssize_t size;
164     char *buf = NULL;
165
166     assert(fname);
167
168 #ifdef ENABLE_CHROOT
169     fd = avahi_chroot_helper_get_fd(fname);
170 #else
171     fd = open(fname, O_RDONLY);
172 #endif
173
174     if (fd < 0) {
175         avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
176         goto fail;
177     }
178
179     if (fstat(fd, &st) < 0) {
180         avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
181         goto fail;
182     }
183
184     if (!(S_ISREG(st.st_mode))) {
185         avahi_log_error("Invalid file %s", fname);
186         goto fail;
187     }
188
189     if (st.st_size > 1024*1024) { /** 1MB */
190         avahi_log_error("File too large %s", fname);
191         goto fail;
192     }
193
194     buf = avahi_new(char, st.st_size+1);
195
196     if ((size = read(fd, buf, st.st_size)) < 0) {
197         avahi_log_error("read() failed: %s\n", strerror(errno));
198         goto fail;
199     }
200
201     buf[size] = 0;
202
203     close(fd);
204
205     return buf;
206
207 fail:
208     if (fd >= 0)
209         close(fd);
210
211     if (buf)
212         avahi_free(buf);
213
214     return NULL;
215
216 }
217
218 DBusHandlerResult avahi_dbus_handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
219     char *contents, *path;
220     DBusError error;
221
222     assert(c);
223     assert(m);
224     assert(fname);
225
226     dbus_error_init(&error);
227
228     if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
229         avahi_log_error("Error parsing Introspect message: %s", error.message);
230         goto fail;
231     }
232
233     path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
234     contents = file_get_contents(path);
235     avahi_free(path);
236
237     if (!contents) {
238         avahi_log_error("Failed to load introspection data.");
239         goto fail;
240     }
241
242     avahi_dbus_respond_string(c, m, contents);
243     avahi_free(contents);
244
245     return DBUS_HANDLER_RESULT_HANDLED;
246
247 fail:
248     if (dbus_error_is_set(&error))
249         dbus_error_free(&error);
250
251     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
252
253 }
254
255 void avahi_dbus_append_string_list(DBusMessage *reply, AvahiStringList *txt) {
256     AvahiStringList *p;
257     DBusMessageIter iter, sub;
258
259     assert(reply);
260
261     dbus_message_iter_init_append(reply, &iter);
262     dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
263
264     for (p = txt; p; p = p->next) {
265         DBusMessageIter sub2;
266         const uint8_t *data = p->text;
267
268         dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
269         dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
270         dbus_message_iter_close_container(&sub, &sub2);
271
272     }
273     dbus_message_iter_close_container(&iter, &sub);
274 }
275
276 int avahi_dbus_read_rdata(DBusMessage *m, int idx, void **rdata, uint32_t *size) {
277     DBusMessageIter iter, sub;
278     int n, j;
279     uint8_t *k;
280
281     assert(m);
282
283     dbus_message_iter_init(m, &iter);
284
285     for (j = 0; j < idx; j++)
286        dbus_message_iter_next(&iter);
287
288     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
289         dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
290         goto fail;
291
292     dbus_message_iter_recurse(&iter, &sub);
293     dbus_message_iter_get_fixed_array(&sub, &k, &n);
294
295     *rdata = k;
296     *size = n;
297
298     return 0;
299
300 fail:
301     avahi_log_warn("Error parsing data");
302
303     *rdata = NULL;
304     size = 0;
305     return -1;
306 }
307
308 int avahi_dbus_read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
309     DBusMessageIter iter, sub;
310     int j;
311     AvahiStringList *strlst = NULL;
312
313     assert(m);
314     assert(l);
315
316     dbus_message_iter_init(m, &iter);
317
318     for (j = 0; j < idx; j++)
319         dbus_message_iter_next(&iter);
320
321     if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
322         dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
323         goto fail;
324
325     dbus_message_iter_recurse(&iter, &sub);
326
327     for (;;) {
328         int at, n;
329         const uint8_t *k;
330         DBusMessageIter sub2;
331
332         if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
333             break;
334
335         assert(at == DBUS_TYPE_ARRAY);
336
337         if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
338             goto fail;
339
340         dbus_message_iter_recurse(&sub, &sub2);
341
342         k = (const uint8_t*) "";
343         n = 0;
344         dbus_message_iter_get_fixed_array(&sub2, &k, &n);
345
346         if (!k)
347             k = (const uint8_t*) "";
348
349         strlst = avahi_string_list_add_arbitrary(strlst, k, n);
350
351         dbus_message_iter_next(&sub);
352     }
353
354     *l = strlst;
355
356     return 0;
357
358 fail:
359     avahi_log_warn("Error parsing TXT data");
360
361     avahi_string_list_free(strlst);
362     *l = NULL;
363     return -1;
364 }
365
366 int avahi_dbus_is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
367     AvahiSEntryGroup *g;
368
369     if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
370         EntryGroupInfo *egi;
371
372         for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
373             if (egi->entry_group == g)
374                 return 1;
375     }
376
377     return 0;
378 }
379
380 int avahi_dbus_append_rdata(DBusMessage *message, const void *rdata, size_t size) {
381     DBusMessageIter iter, sub;
382
383     assert(message);
384
385     dbus_message_iter_init_append(message, &iter);
386
387     if (!(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &sub)) ||
388         !(dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &rdata, size)) ||
389         !(dbus_message_iter_close_container(&iter, &sub)))
390         return -1;
391
392     return 0;
393 }