Home | History | Annotate | Download | only in avahi-daemon
      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/avahi-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 
     36 void 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 
     54 void 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 
     89 DBusHandlerResult 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 
    364 fail:
    365     if (dbus_error_is_set(&error))
    366         dbus_error_free(&error);
    367 
    368     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
    369 }
    370