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