Home | History | Annotate | Download | only in avahi-client
      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 <stdlib.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 
     28 #include <dbus/dbus.h>
     29 
     30 #include <avahi-client/client.h>
     31 #include <avahi-common/dbus.h>
     32 #include <avahi-common/llist.h>
     33 #include <avahi-common/error.h>
     34 #include "avahi-common/avahi-malloc.h"
     35 
     36 #include "client.h"
     37 #include "internal.h"
     38 
     39 void avahi_entry_group_set_state(AvahiEntryGroup *group, AvahiEntryGroupState state) {
     40     assert(group);
     41 
     42     if (group->state_valid && group->state == state)
     43         return;
     44 
     45     group->state = state;
     46     group->state_valid = 1;
     47 
     48     if (group->callback)
     49         group->callback(group, state, group->userdata);
     50 }
     51 
     52 static int retrieve_state(AvahiEntryGroup *group) {
     53     DBusMessage *message = NULL, *reply = NULL;
     54     DBusError error;
     55     int r = AVAHI_OK;
     56     int32_t state;
     57     AvahiClient *client;
     58 
     59     dbus_error_init(&error);
     60 
     61     assert(group);
     62     client = group->client;
     63 
     64     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState"))) {
     65         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
     66         goto fail;
     67     }
     68 
     69     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
     70         dbus_error_is_set (&error)) {
     71         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
     72         goto fail;
     73     }
     74 
     75     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &state, DBUS_TYPE_INVALID) ||
     76         dbus_error_is_set (&error)) {
     77         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
     78         goto fail;
     79     }
     80 
     81     dbus_message_unref(message);
     82     dbus_message_unref(reply);
     83 
     84     return state;
     85 
     86 fail:
     87     if (dbus_error_is_set(&error)) {
     88         r = avahi_client_set_dbus_error(client, &error);
     89         dbus_error_free(&error);
     90     }
     91 
     92     if (message)
     93         dbus_message_unref(message);
     94 
     95     if (reply)
     96         dbus_message_unref(reply);
     97 
     98     return r;
     99 }
    100 
    101 AvahiEntryGroup* avahi_entry_group_new (AvahiClient *client, AvahiEntryGroupCallback callback, void *userdata) {
    102     AvahiEntryGroup *group = NULL;
    103     DBusMessage *message = NULL, *reply = NULL;
    104     DBusError error;
    105     char *path;
    106     int state;
    107 
    108     assert(client);
    109 
    110     dbus_error_init (&error);
    111 
    112     if (!avahi_client_is_connected(client)) {
    113         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
    114         goto fail;
    115     }
    116 
    117     if (!(group = avahi_new(AvahiEntryGroup, 1))) {
    118         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    119         goto fail;
    120     }
    121 
    122     group->client = client;
    123     group->callback = callback;
    124     group->userdata = userdata;
    125     group->state_valid = 0;
    126     group->path = NULL;
    127     AVAHI_LLIST_PREPEND(AvahiEntryGroup, groups, client->groups, group);
    128 
    129     if (!(message = dbus_message_new_method_call(
    130               AVAHI_DBUS_NAME,
    131               AVAHI_DBUS_PATH_SERVER,
    132               AVAHI_DBUS_INTERFACE_SERVER,
    133               "EntryGroupNew"))) {
    134         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    135         goto fail;
    136     }
    137 
    138     if (!(reply = dbus_connection_send_with_reply_and_block (client->bus, message, -1, &error)) ||
    139         dbus_error_is_set (&error)) {
    140         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
    141         goto fail;
    142     }
    143 
    144     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID) ||
    145         dbus_error_is_set (&error)) {
    146         avahi_client_set_errno (client, AVAHI_ERR_DBUS_ERROR);
    147         goto fail;
    148     }
    149 
    150     if (!(group->path = avahi_strdup (path))) {
    151 
    152         /* FIXME: We don't remove the object on the server side */
    153 
    154         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    155         goto fail;
    156     }
    157 
    158     if ((state = retrieve_state(group)) < 0) {
    159         avahi_client_set_errno(client, state);
    160         goto fail;
    161     }
    162 
    163     avahi_entry_group_set_state(group, (AvahiEntryGroupState) state);
    164 
    165     dbus_message_unref(message);
    166     dbus_message_unref(reply);
    167 
    168     return group;
    169 
    170 fail:
    171     if (dbus_error_is_set(&error)) {
    172         avahi_client_set_dbus_error(client, &error);
    173         dbus_error_free(&error);
    174     }
    175 
    176     if (group)
    177         avahi_entry_group_free(group);
    178 
    179     if (message)
    180         dbus_message_unref(message);
    181 
    182     if (reply)
    183         dbus_message_unref(reply);
    184 
    185     return NULL;
    186 }
    187 
    188 static int entry_group_simple_method_call(AvahiEntryGroup *group, const char *method) {
    189     DBusMessage *message = NULL, *reply = NULL;
    190     DBusError error;
    191     int r = AVAHI_OK;
    192     AvahiClient *client;
    193 
    194     dbus_error_init(&error);
    195 
    196     assert(group);
    197     client = group->client;
    198 
    199     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, method))) {
    200         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    201         goto fail;
    202     }
    203 
    204     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    205         dbus_error_is_set (&error)) {
    206         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    207         goto fail;
    208     }
    209 
    210     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
    211         dbus_error_is_set (&error)) {
    212         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    213         goto fail;
    214     }
    215 
    216     dbus_message_unref(message);
    217     dbus_message_unref(reply);
    218 
    219     return AVAHI_OK;
    220 
    221 fail:
    222     if (dbus_error_is_set(&error)) {
    223         r = avahi_client_set_dbus_error(client, &error);
    224         dbus_error_free(&error);
    225     }
    226 
    227     if (message)
    228         dbus_message_unref(message);
    229 
    230     if (reply)
    231         dbus_message_unref(reply);
    232 
    233     return r;
    234 }
    235 
    236 int avahi_entry_group_free(AvahiEntryGroup *group) {
    237     AvahiClient *client = group->client;
    238     int r = AVAHI_OK;
    239 
    240     assert(group);
    241 
    242     if (group->path && avahi_client_is_connected(client))
    243         r = entry_group_simple_method_call(group, "Free");
    244 
    245     AVAHI_LLIST_REMOVE(AvahiEntryGroup, groups, client->groups, group);
    246 
    247     avahi_free(group->path);
    248     avahi_free(group);
    249 
    250     return r;
    251 }
    252 
    253 int avahi_entry_group_commit(AvahiEntryGroup *group) {
    254     int ret;
    255     assert(group);
    256 
    257     if (!group->path || !avahi_client_is_connected(group->client))
    258         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    259 
    260     if ((ret = entry_group_simple_method_call(group, "Commit")) < 0)
    261         return ret;
    262 
    263     group->state_valid = 0;
    264     return ret;
    265 }
    266 
    267 int avahi_entry_group_reset(AvahiEntryGroup *group) {
    268     int ret;
    269     assert(group);
    270 
    271     if (!group->path || !avahi_client_is_connected(group->client))
    272         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    273 
    274     if ((ret = entry_group_simple_method_call(group, "Reset")) < 0)
    275         return ret;
    276 
    277     group->state_valid = 0;
    278     return ret;
    279 }
    280 
    281 int avahi_entry_group_get_state (AvahiEntryGroup *group) {
    282     assert (group);
    283 
    284     if (group->state_valid)
    285         return group->state;
    286 
    287     return retrieve_state(group);
    288 }
    289 
    290 AvahiClient* avahi_entry_group_get_client (AvahiEntryGroup *group) {
    291     assert(group);
    292 
    293     return group->client;
    294 }
    295 
    296 int avahi_entry_group_is_empty (AvahiEntryGroup *group) {
    297     DBusMessage *message = NULL, *reply = NULL;
    298     DBusError error;
    299     int r = AVAHI_OK;
    300     int b;
    301     AvahiClient *client;
    302 
    303     assert(group);
    304     client = group->client;
    305 
    306     if (!group->path || !avahi_client_is_connected(group->client))
    307         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    308 
    309     dbus_error_init(&error);
    310 
    311     if (!(message = dbus_message_new_method_call(AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty"))) {
    312         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    313         goto fail;
    314     }
    315 
    316     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    317         dbus_error_is_set (&error)) {
    318         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    319         goto fail;
    320     }
    321 
    322     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID) ||
    323         dbus_error_is_set (&error)) {
    324         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    325         goto fail;
    326     }
    327 
    328     dbus_message_unref(message);
    329     dbus_message_unref(reply);
    330 
    331     return !!b;
    332 
    333 fail:
    334     if (dbus_error_is_set(&error)) {
    335         r = avahi_client_set_dbus_error(client, &error);
    336         dbus_error_free(&error);
    337     }
    338 
    339     if (message)
    340         dbus_message_unref(message);
    341 
    342     if (reply)
    343         dbus_message_unref(reply);
    344 
    345     return r;
    346 }
    347 
    348 static int append_rdata(DBusMessage *message, const void *rdata, size_t size) {
    349     DBusMessageIter iter, sub;
    350 
    351     assert(message);
    352 
    353     dbus_message_iter_init_append(message, &iter);
    354 
    355     if (!(dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &sub)) ||
    356         !(dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &rdata, size)) ||
    357         !(dbus_message_iter_close_container(&iter, &sub)))
    358         return -1;
    359 
    360     return 0;
    361 }
    362 
    363 static int append_string_list(DBusMessage *message, AvahiStringList *txt) {
    364     DBusMessageIter iter, sub;
    365     int r = -1;
    366     AvahiStringList *p;
    367 
    368     assert(message);
    369 
    370     dbus_message_iter_init_append(message, &iter);
    371 
    372     /* Reverse the string list, so that we can pass it in-order to the server */
    373     txt = avahi_string_list_reverse(txt);
    374 
    375     if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub))
    376         goto fail;
    377 
    378     /* Assemble the AvahiStringList into an Array of Array of Bytes to send over dbus */
    379     for (p = txt; p != NULL; p = p->next) {
    380         DBusMessageIter sub2;
    381         const uint8_t *data = p->text;
    382 
    383         if (!(dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2)) ||
    384             !(dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size)) ||
    385             !(dbus_message_iter_close_container(&sub, &sub2)))
    386             goto fail;
    387     }
    388 
    389     if (!dbus_message_iter_close_container(&iter, &sub))
    390         goto fail;
    391 
    392     r = 0;
    393 
    394 fail:
    395 
    396     /* Reverse the string list to the original state */
    397     txt = avahi_string_list_reverse(txt);
    398 
    399     return r;
    400 }
    401 
    402 int avahi_entry_group_add_service_strlst(
    403     AvahiEntryGroup *group,
    404     AvahiIfIndex interface,
    405     AvahiProtocol protocol,
    406     AvahiPublishFlags flags,
    407     const char *name,
    408     const char *type,
    409     const char *domain,
    410     const char *host,
    411     uint16_t port,
    412     AvahiStringList *txt) {
    413 
    414     DBusMessage *message = NULL, *reply = NULL;
    415     int r = AVAHI_OK;
    416     DBusError error;
    417     AvahiClient *client;
    418     int32_t i_interface, i_protocol;
    419     uint32_t u_flags;
    420 
    421     assert(group);
    422     assert(name);
    423     assert(type);
    424 
    425     client = group->client;
    426 
    427     if (!group->path || !avahi_client_is_connected(group->client))
    428         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    429 
    430     if (!domain)
    431         domain = "";
    432 
    433     if (!host)
    434         host = "";
    435 
    436     dbus_error_init(&error);
    437 
    438     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService"))) {
    439         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    440         goto fail;
    441     }
    442 
    443     i_interface = (int32_t) interface;
    444     i_protocol = (int32_t) protocol;
    445     u_flags = (uint32_t) flags;
    446 
    447     if (!dbus_message_append_args(
    448             message,
    449             DBUS_TYPE_INT32, &i_interface,
    450             DBUS_TYPE_INT32, &i_protocol,
    451             DBUS_TYPE_UINT32, &u_flags,
    452             DBUS_TYPE_STRING, &name,
    453             DBUS_TYPE_STRING, &type,
    454             DBUS_TYPE_STRING, &domain,
    455             DBUS_TYPE_STRING, &host,
    456             DBUS_TYPE_UINT16, &port,
    457             DBUS_TYPE_INVALID) ||
    458         append_string_list(message, txt) < 0) {
    459         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
    460         goto fail;
    461     }
    462 
    463     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    464         dbus_error_is_set (&error)) {
    465         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    466         goto fail;
    467     }
    468 
    469     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
    470         dbus_error_is_set (&error)) {
    471         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    472         goto fail;
    473     }
    474 
    475     dbus_message_unref(message);
    476     dbus_message_unref(reply);
    477 
    478     return AVAHI_OK;
    479 
    480 fail:
    481 
    482     if (dbus_error_is_set(&error)) {
    483         r = avahi_client_set_dbus_error(client, &error);
    484         dbus_error_free(&error);
    485     }
    486 
    487     if (message)
    488         dbus_message_unref(message);
    489 
    490     if (reply)
    491         dbus_message_unref(reply);
    492 
    493     return r;
    494 }
    495 
    496 int avahi_entry_group_add_service(
    497     AvahiEntryGroup *group,
    498     AvahiIfIndex interface,
    499     AvahiProtocol protocol,
    500     AvahiPublishFlags flags,
    501     const char *name,
    502     const char *type,
    503     const char *domain,
    504     const char *host,
    505     uint16_t port,
    506     ...) {
    507 
    508     va_list va;
    509     int r;
    510     AvahiStringList *txt;
    511 
    512     assert(group);
    513 
    514     va_start(va, port);
    515     txt = avahi_string_list_new_va(va);
    516     r = avahi_entry_group_add_service_strlst(group, interface, protocol, flags, name, type, domain, host, port, txt);
    517     avahi_string_list_free(txt);
    518     va_end(va);
    519     return r;
    520 }
    521 
    522 int avahi_entry_group_add_service_subtype(
    523     AvahiEntryGroup *group,
    524     AvahiIfIndex interface,
    525     AvahiProtocol protocol,
    526     AvahiPublishFlags flags,
    527     const char *name,
    528     const char *type,
    529     const char *domain,
    530     const char *subtype) {
    531 
    532     DBusMessage *message = NULL, *reply = NULL;
    533     int r = AVAHI_OK;
    534     DBusError error;
    535     AvahiClient *client;
    536     int32_t i_interface, i_protocol;
    537     uint32_t u_flags;
    538 
    539     assert(group);
    540     assert(name);
    541     assert(type);
    542     assert(subtype);
    543 
    544     client = group->client;
    545 
    546     if (!group->path || !avahi_client_is_connected(group->client))
    547         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    548 
    549     if (!domain)
    550         domain = "";
    551 
    552     dbus_error_init(&error);
    553 
    554     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype"))) {
    555         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    556         goto fail;
    557     }
    558 
    559     i_interface = (int32_t) interface;
    560     i_protocol = (int32_t) protocol;
    561     u_flags = (uint32_t) flags;
    562 
    563     if (!dbus_message_append_args(
    564             message,
    565             DBUS_TYPE_INT32, &i_interface,
    566             DBUS_TYPE_INT32, &i_protocol,
    567             DBUS_TYPE_UINT32, &u_flags,
    568             DBUS_TYPE_STRING, &name,
    569             DBUS_TYPE_STRING, &type,
    570             DBUS_TYPE_STRING, &domain,
    571             DBUS_TYPE_STRING, &subtype,
    572             DBUS_TYPE_INVALID)) {
    573         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
    574         goto fail;
    575     }
    576 
    577     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    578         dbus_error_is_set (&error)) {
    579         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    580         goto fail;
    581     }
    582 
    583     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
    584         dbus_error_is_set (&error)) {
    585         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    586         goto fail;
    587     }
    588 
    589     dbus_message_unref(message);
    590     dbus_message_unref(reply);
    591 
    592     return AVAHI_OK;
    593 
    594 fail:
    595 
    596     if (dbus_error_is_set(&error)) {
    597         r = avahi_client_set_dbus_error(client, &error);
    598         dbus_error_free(&error);
    599     }
    600 
    601     if (message)
    602         dbus_message_unref(message);
    603 
    604     if (reply)
    605         dbus_message_unref(reply);
    606 
    607     return r;
    608 
    609 }
    610 
    611 int avahi_entry_group_update_service_txt(
    612     AvahiEntryGroup *group,
    613     AvahiIfIndex interface,
    614     AvahiProtocol protocol,
    615     AvahiPublishFlags flags,
    616     const char *name,
    617     const char *type,
    618     const char *domain,
    619     ...) {
    620 
    621     va_list va;
    622     int r;
    623     AvahiStringList *txt;
    624 
    625     va_start(va, domain);
    626     txt = avahi_string_list_new_va(va);
    627     r = avahi_entry_group_update_service_txt_strlst(group, interface, protocol, flags, name, type, domain, txt);
    628     avahi_string_list_free(txt);
    629     va_end(va);
    630     return r;
    631 }
    632 
    633 int avahi_entry_group_update_service_txt_strlst(
    634     AvahiEntryGroup *group,
    635     AvahiIfIndex interface,
    636     AvahiProtocol protocol,
    637     AvahiPublishFlags flags,
    638     const char *name,
    639     const char *type,
    640     const char *domain,
    641     AvahiStringList *txt) {
    642 
    643     DBusMessage *message = NULL, *reply = NULL;
    644     int r = AVAHI_OK;
    645     DBusError error;
    646     AvahiClient *client;
    647     int32_t i_interface, i_protocol;
    648     uint32_t u_flags;
    649 
    650     assert(group);
    651     assert(name);
    652     assert(type);
    653 
    654     client = group->client;
    655 
    656     if (!group->path || !avahi_client_is_connected(group->client))
    657         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    658 
    659     if (!domain)
    660         domain = "";
    661 
    662     dbus_error_init(&error);
    663 
    664     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt"))) {
    665         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    666         goto fail;
    667     }
    668 
    669     i_interface = (int32_t) interface;
    670     i_protocol = (int32_t) protocol;
    671     u_flags = (uint32_t) flags;
    672 
    673     if (!dbus_message_append_args(
    674             message,
    675             DBUS_TYPE_INT32, &i_interface,
    676             DBUS_TYPE_INT32, &i_protocol,
    677             DBUS_TYPE_UINT32, &u_flags,
    678             DBUS_TYPE_STRING, &name,
    679             DBUS_TYPE_STRING, &type,
    680             DBUS_TYPE_STRING, &domain,
    681             DBUS_TYPE_INVALID) ||
    682         append_string_list(message, txt) < 0) {
    683         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
    684         goto fail;
    685     }
    686 
    687     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    688         dbus_error_is_set (&error)) {
    689         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    690         goto fail;
    691     }
    692 
    693     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
    694         dbus_error_is_set (&error)) {
    695         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    696         goto fail;
    697     }
    698 
    699     dbus_message_unref(message);
    700     dbus_message_unref(reply);
    701 
    702     return AVAHI_OK;
    703 
    704 fail:
    705 
    706     if (dbus_error_is_set(&error)) {
    707         r = avahi_client_set_dbus_error(client, &error);
    708         dbus_error_free(&error);
    709     }
    710 
    711     if (message)
    712         dbus_message_unref(message);
    713 
    714     if (reply)
    715         dbus_message_unref(reply);
    716 
    717     return r;
    718 }
    719 
    720 /** Add a host/address pair */
    721 int avahi_entry_group_add_address(
    722     AvahiEntryGroup *group,
    723     AvahiIfIndex interface,
    724     AvahiProtocol protocol,
    725     AvahiPublishFlags flags,
    726     const char *name,
    727     const AvahiAddress *a) {
    728 
    729     DBusMessage *message = NULL, *reply = NULL;
    730     int r = AVAHI_OK;
    731     DBusError error;
    732     AvahiClient *client;
    733     int32_t i_interface, i_protocol;
    734     uint32_t u_flags;
    735     char s_address[AVAHI_ADDRESS_STR_MAX];
    736     char *p_address = s_address;
    737 
    738     assert(name);
    739 
    740     client = group->client;
    741 
    742     if (!group->path || !avahi_client_is_connected(group->client))
    743         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    744 
    745     dbus_error_init(&error);
    746 
    747     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress"))) {
    748         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    749         goto fail;
    750     }
    751 
    752     i_interface = (int32_t) interface;
    753     i_protocol = (int32_t) protocol;
    754     u_flags = (uint32_t) flags;
    755 
    756     if (!avahi_address_snprint (s_address, sizeof (s_address), a))
    757     {
    758         r = avahi_client_set_errno(client, AVAHI_ERR_INVALID_ADDRESS);
    759         goto fail;
    760     }
    761 
    762     if (!dbus_message_append_args(
    763             message,
    764             DBUS_TYPE_INT32, &i_interface,
    765             DBUS_TYPE_INT32, &i_protocol,
    766             DBUS_TYPE_UINT32, &u_flags,
    767             DBUS_TYPE_STRING, &name,
    768             DBUS_TYPE_STRING, &p_address,
    769             DBUS_TYPE_INVALID)) {
    770         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
    771         goto fail;
    772     }
    773 
    774     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    775         dbus_error_is_set (&error)) {
    776         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    777         goto fail;
    778     }
    779 
    780     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
    781         dbus_error_is_set (&error)) {
    782         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    783         goto fail;
    784     }
    785 
    786     dbus_message_unref(message);
    787     dbus_message_unref(reply);
    788 
    789     return AVAHI_OK;
    790 
    791 fail:
    792 
    793     if (dbus_error_is_set(&error)) {
    794         r = avahi_client_set_dbus_error(client, &error);
    795         dbus_error_free(&error);
    796     }
    797 
    798     if (message)
    799         dbus_message_unref(message);
    800 
    801     if (reply)
    802         dbus_message_unref(reply);
    803 
    804     return r;
    805 }
    806 
    807 /** Add an arbitrary record */
    808 int avahi_entry_group_add_record(
    809     AvahiEntryGroup *group,
    810     AvahiIfIndex interface,
    811     AvahiProtocol protocol,
    812     AvahiPublishFlags flags,
    813     const char *name,
    814     uint16_t clazz,
    815     uint16_t type,
    816     uint32_t ttl,
    817     const void *rdata,
    818     size_t size) {
    819 
    820     DBusMessage *message = NULL, *reply = NULL;
    821     int r = AVAHI_OK;
    822     DBusError error;
    823     AvahiClient *client;
    824     int32_t i_interface, i_protocol;
    825     uint32_t u_flags;
    826 
    827     assert(name);
    828 
    829     client = group->client;
    830 
    831     if (!group->path || !avahi_client_is_connected(group->client))
    832         return avahi_client_set_errno(group->client, AVAHI_ERR_BAD_STATE);
    833 
    834     dbus_error_init(&error);
    835 
    836     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, group->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord"))) {
    837         r = avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
    838         goto fail;
    839     }
    840 
    841     i_interface = (int32_t) interface;
    842     i_protocol = (int32_t) protocol;
    843     u_flags = (uint32_t) flags;
    844 
    845     if (!dbus_message_append_args(
    846             message,
    847             DBUS_TYPE_INT32, &i_interface,
    848             DBUS_TYPE_INT32, &i_protocol,
    849             DBUS_TYPE_UINT32, &u_flags,
    850             DBUS_TYPE_STRING, &name,
    851             DBUS_TYPE_UINT16, &clazz,
    852             DBUS_TYPE_UINT16, &type,
    853             DBUS_TYPE_UINT32, &ttl,
    854             DBUS_TYPE_INVALID) || append_rdata(message, rdata, size) < 0) {
    855         r = avahi_client_set_errno(group->client, AVAHI_ERR_NO_MEMORY);
    856         goto fail;
    857     }
    858 
    859     if (!(reply = dbus_connection_send_with_reply_and_block(client->bus, message, -1, &error)) ||
    860         dbus_error_is_set (&error)) {
    861         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    862         goto fail;
    863     }
    864 
    865     if (!dbus_message_get_args(reply, &error, DBUS_TYPE_INVALID) ||
    866         dbus_error_is_set (&error)) {
    867         r = avahi_client_set_errno(client, AVAHI_ERR_DBUS_ERROR);
    868         goto fail;
    869     }
    870 
    871     dbus_message_unref(message);
    872     dbus_message_unref(reply);
    873 
    874     return AVAHI_OK;
    875 
    876 fail:
    877 
    878     if (dbus_error_is_set(&error)) {
    879         r = avahi_client_set_dbus_error(client, &error);
    880         dbus_error_free(&error);
    881     }
    882 
    883     if (message)
    884         dbus_message_unref(message);
    885 
    886     if (reply)
    887         dbus_message_unref(reply);
    888 
    889     return r;
    890 }
    891