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 <string.h> 27 28#include <avahi-common/malloc.h> 29#include <avahi-common/dbus.h> 30#include <avahi-common/error.h> 31#include <avahi-common/domain.h> 32#include <avahi-core/log.h> 33 34#include "dbus-util.h" 35#include "dbus-internal.h" 36#include "main.h" 37 38void avahi_dbus_entry_group_free(EntryGroupInfo *i) { 39 assert(i); 40 41 if (i->entry_group) 42 avahi_s_entry_group_free(i->entry_group); 43 44 if (i->path) { 45 dbus_connection_unregister_object_path(server->bus, i->path); 46 avahi_free(i->path); 47 } 48 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i); 49 50 i->client->n_objects--; 51 assert(i->client->n_objects >= 0); 52 53 avahi_free(i); 54} 55 56void avahi_dbus_entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) { 57 EntryGroupInfo *i = userdata; 58 DBusMessage *m; 59 int32_t t; 60 const char *e; 61 62 assert(s); 63 assert(g); 64 assert(i); 65 66 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged"); 67 68 t = (int32_t) state; 69 if (state == AVAHI_ENTRY_GROUP_FAILURE) 70 e = avahi_error_number_to_dbus(avahi_server_errno(s)); 71 else if (state == AVAHI_ENTRY_GROUP_COLLISION) 72 e = AVAHI_DBUS_ERR_COLLISION; 73 else 74 e = AVAHI_DBUS_ERR_OK; 75 76 dbus_message_append_args( 77 m, 78 DBUS_TYPE_INT32, &t, 79 DBUS_TYPE_STRING, &e, 80 DBUS_TYPE_INVALID); 81 dbus_message_set_destination(m, i->client->name); 82 dbus_connection_send(server->bus, m, NULL); 83 dbus_message_unref(m); 84} 85 86DBusHandlerResult avahi_dbus_msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) { 87 DBusError error; 88 EntryGroupInfo *i = userdata; 89 90 assert(c); 91 assert(m); 92 assert(i); 93 94 dbus_error_init(&error); 95 96 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", 97 dbus_message_get_interface(m), 98 dbus_message_get_path(m), 99 dbus_message_get_member(m)); 100 101 /* Introspection */ 102 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) 103 return avahi_dbus_handle_introspect(c, m, "EntryGroup.introspect"); 104 105 /* Access control */ 106 if (strcmp(dbus_message_get_sender(m), i->client->name)) 107 return avahi_dbus_respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL); 108 109 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) { 110 111 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 112 avahi_log_warn("Error parsing EntryGroup::Free message"); 113 goto fail; 114 } 115 116 avahi_dbus_entry_group_free(i); 117 return avahi_dbus_respond_ok(c, m); 118 119 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) { 120 121 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 122 avahi_log_warn("Error parsing EntryGroup::Commit message"); 123 goto fail; 124 } 125 126 if (avahi_s_entry_group_commit(i->entry_group) < 0) 127 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 128 129 return avahi_dbus_respond_ok(c, m); 130 131 132 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) { 133 134 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 135 avahi_log_warn("Error parsing EntryGroup::Reset message"); 136 goto fail; 137 } 138 139 avahi_s_entry_group_reset(i->entry_group); 140 i->n_entries = 0; 141 return avahi_dbus_respond_ok(c, m); 142 143 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) { 144 145 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 146 avahi_log_warn("Error parsing EntryGroup::IsEmpty message"); 147 goto fail; 148 } 149 150 return avahi_dbus_respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group)); 151 152 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) { 153 AvahiEntryGroupState state; 154 155 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { 156 avahi_log_warn("Error parsing EntryGroup::GetState message"); 157 goto fail; 158 } 159 160 state = avahi_s_entry_group_get_state(i->entry_group); 161 return avahi_dbus_respond_int32(c, m, (int32_t) state); 162 163 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) { 164 int32_t interface, protocol; 165 uint32_t flags; 166 char *type, *name, *domain, *host; 167 uint16_t port; 168 AvahiStringList *strlst = NULL; 169 170 if (!dbus_message_get_args( 171 m, &error, 172 DBUS_TYPE_INT32, &interface, 173 DBUS_TYPE_INT32, &protocol, 174 DBUS_TYPE_UINT32, &flags, 175 DBUS_TYPE_STRING, &name, 176 DBUS_TYPE_STRING, &type, 177 DBUS_TYPE_STRING, &domain, 178 DBUS_TYPE_STRING, &host, 179 DBUS_TYPE_UINT16, &port, 180 DBUS_TYPE_INVALID) || 181 !type || !name || 182 avahi_dbus_read_strlst(m, 8, &strlst) < 0) { 183 avahi_log_warn("Error parsing EntryGroup::AddService message"); 184 goto fail; 185 } 186 187 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) { 188 avahi_string_list_free(strlst); 189 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); 190 } 191 192 if (domain && !*domain) 193 domain = NULL; 194 195 if (host && !*host) 196 host = NULL; 197 198 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) { 199 avahi_string_list_free(strlst); 200 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 201 } 202 203 if (!(flags & AVAHI_PUBLISH_UPDATE)) 204 i->n_entries ++; 205 206 avahi_string_list_free(strlst); 207 208 return avahi_dbus_respond_ok(c, m); 209 210 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) { 211 212 int32_t interface, protocol; 213 uint32_t flags; 214 char *type, *name, *domain, *subtype; 215 216 if (!dbus_message_get_args( 217 m, &error, 218 DBUS_TYPE_INT32, &interface, 219 DBUS_TYPE_INT32, &protocol, 220 DBUS_TYPE_UINT32, &flags, 221 DBUS_TYPE_STRING, &name, 222 DBUS_TYPE_STRING, &type, 223 DBUS_TYPE_STRING, &domain, 224 DBUS_TYPE_STRING, &subtype, 225 DBUS_TYPE_INVALID) || !type || !name || !subtype) { 226 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message"); 227 goto fail; 228 } 229 230 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) 231 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); 232 233 if (domain && !*domain) 234 domain = NULL; 235 236 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0) 237 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 238 239 if (!(flags & AVAHI_PUBLISH_UPDATE)) 240 i->n_entries ++; 241 242 return avahi_dbus_respond_ok(c, m); 243 244 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) { 245 int32_t interface, protocol; 246 uint32_t flags; 247 char *type, *name, *domain; 248 AvahiStringList *strlst; 249 250 if (!dbus_message_get_args( 251 m, &error, 252 DBUS_TYPE_INT32, &interface, 253 DBUS_TYPE_INT32, &protocol, 254 DBUS_TYPE_UINT32, &flags, 255 DBUS_TYPE_STRING, &name, 256 DBUS_TYPE_STRING, &type, 257 DBUS_TYPE_STRING, &domain, 258 DBUS_TYPE_INVALID) || 259 !type || !name || 260 avahi_dbus_read_strlst(m, 6, &strlst)) { 261 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message"); 262 goto fail; 263 } 264 265 if (domain && !*domain) 266 domain = NULL; 267 268 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) { 269 avahi_string_list_free(strlst); 270 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 271 } 272 273 avahi_string_list_free(strlst); 274 275 return avahi_dbus_respond_ok(c, m); 276 277 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) { 278 int32_t interface, protocol; 279 uint32_t flags; 280 char *name, *address; 281 AvahiAddress a; 282 283 if (!dbus_message_get_args( 284 m, &error, 285 DBUS_TYPE_INT32, &interface, 286 DBUS_TYPE_INT32, &protocol, 287 DBUS_TYPE_UINT32, &flags, 288 DBUS_TYPE_STRING, &name, 289 DBUS_TYPE_STRING, &address, 290 DBUS_TYPE_INVALID) || !name || !address) { 291 avahi_log_warn("Error parsing EntryGroup::AddAddress message"); 292 goto fail; 293 } 294 295 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) 296 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); 297 298 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) 299 return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL); 300 301 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0) 302 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 303 304 if (!(flags & AVAHI_PUBLISH_UPDATE)) 305 i->n_entries ++; 306 307 return avahi_dbus_respond_ok(c, m); 308 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord")) { 309 int32_t interface, protocol; 310 uint32_t flags, ttl, size; 311 uint16_t clazz, type; 312 char *name; 313 void *rdata; 314 AvahiRecord *r; 315 316 if (!dbus_message_get_args( 317 m, &error, 318 DBUS_TYPE_INT32, &interface, 319 DBUS_TYPE_INT32, &protocol, 320 DBUS_TYPE_UINT32, &flags, 321 DBUS_TYPE_STRING, &name, 322 DBUS_TYPE_UINT16, &clazz, 323 DBUS_TYPE_UINT16, &type, 324 DBUS_TYPE_UINT32, &ttl, 325 DBUS_TYPE_INVALID) || !name || 326 avahi_dbus_read_rdata (m, 7, &rdata, &size)) { 327 avahi_log_warn("Error parsing EntryGroup::AddRecord message"); 328 goto fail; 329 } 330 331 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) 332 return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL); 333 334 if (!avahi_is_valid_domain_name (name)) 335 return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL); 336 337 if (!(r = avahi_record_new_full (name, clazz, type, ttl))) 338 return avahi_dbus_respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL); 339 340 if (avahi_rdata_parse (r, rdata, size) < 0) { 341 avahi_record_unref (r); 342 return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL); 343 } 344 345 if (avahi_server_add(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, r) < 0) { 346 avahi_record_unref (r); 347 return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); 348 } 349 350 if (!(flags & AVAHI_PUBLISH_UPDATE)) 351 i->n_entries ++; 352 353 avahi_record_unref (r); 354 355 return avahi_dbus_respond_ok(c, m); 356 } 357 358 359 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m)); 360 361fail: 362 if (dbus_error_is_set(&error)) 363 dbus_error_free(&error); 364 365 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; 366} 367