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