]> git.meshlink.io Git - catta/blobdiff - avahi-daemon/dbus-protocol.c
* nicer display of txt records
[catta] / avahi-daemon / dbus-protocol.c
index 965ffd5e30fcfd6213297472da10e624a65aa658..a42cb2b3e57b7dde470e8f5ca590dacce1ff282a 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <net/if.h>
 #include <errno.h>
@@ -45,6 +46,7 @@
 #include <avahi-common/dbus-watch-glue.h>
 #include <avahi-common/alternative.h>
 #include <avahi-common/error.h>
+#include <avahi-common/domain.h>
 
 #include <avahi-core/log.h>
 #include <avahi-core/core.h>
@@ -67,9 +69,9 @@ typedef struct ServiceBrowserInfo ServiceBrowserInfo;
 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
 
-#define MAX_CLIENTS 20
-#define MAX_OBJECTS_PER_CLIENT 50
-#define MAX_ENTRIES_PER_ENTRY_GROUP 20
+#define CLIENTS_MAX 256
+#define OBJECTS_PER_CLIENT_MAX 50
+#define ENTRIES_PER_ENTRY_GROUP_MAX 20
 
 /* #define VALGRIND_WORKAROUND 1 */
 
@@ -393,7 +395,7 @@ static Client *client_get(const char *name, int create) {
     if (!create)
         return NULL;
 
-    if (server->n_clients >= MAX_CLIENTS)
+    if (server->n_clients >= CLIENTS_MAX)
         return NULL;
     
     /* If not existant yet, create a new entry */
@@ -626,7 +628,7 @@ fail:
 
 }
 
-static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
+static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
     DBusError error;
 
     dbus_error_init(&error);
@@ -685,19 +687,64 @@ static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntry
     EntryGroupInfo *i = userdata;
     DBusMessage *m;
     int32_t t;
+    const char *e;
     
     assert(s);
     assert(g);
     assert(i);
 
     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
+    
     t = (int32_t) state;
-    dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
+    if (state == AVAHI_ENTRY_GROUP_FAILURE)
+        e = avahi_error_number_to_dbus(avahi_server_errno(s));
+    else if (state == AVAHI_ENTRY_GROUP_COLLISION)
+        e = AVAHI_DBUS_ERR_COLLISION;
+    else
+        e = AVAHI_DBUS_ERR_OK;
+        
+    dbus_message_append_args(
+        m,
+        DBUS_TYPE_INT32, &t,
+        DBUS_TYPE_STRING, &e,
+        DBUS_TYPE_INVALID);
     dbus_message_set_destination(m, i->client->name);  
     dbus_connection_send(server->bus, m, NULL);
     dbus_message_unref(m);
 }
 
+static int read_rdata(DBusMessage *m, int idx, void **rdata, uint32_t *size) {
+    DBusMessageIter iter, sub;
+    int n, j;
+    uint8_t *k;
+
+    assert(m);
+    
+    dbus_message_iter_init(m, &iter);
+
+    for (j = 0; j < idx; j++)
+       dbus_message_iter_next(&iter);
+    
+    if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+        dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
+        goto fail;
+
+    dbus_message_iter_recurse(&iter, &sub);
+    dbus_message_iter_get_fixed_array(&sub, &k, &n);
+
+    *rdata = k;
+    *size = n;
+    
+    return 0;
+    
+fail:
+    avahi_log_warn("Error parsing data");
+
+    *rdata = NULL;
+    size = 0;
+    return -1;
+}
+
 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
     DBusMessageIter iter, sub;
     int j;
@@ -849,7 +896,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
             goto fail;
         }
 
-        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
+        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) {
             avahi_string_list_free(strlst);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
         }
@@ -892,7 +939,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
             goto fail;
         }
 
-        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
+        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
 
         if (domain && !*domain)
@@ -957,7 +1004,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
             goto fail;
         }
 
-        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
+        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
         
         if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
@@ -969,8 +1016,57 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
         if (!(flags & AVAHI_PUBLISH_UPDATE))
             i->n_entries ++;
         
+        return respond_ok(c, m);
+    } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord")) {
+        int32_t interface, protocol;
+        uint32_t flags, ttl, size;
+        uint16_t clazz, type;
+        char *name;
+        void *rdata;
+        AvahiRecord *r;
+        
+        if (!dbus_message_get_args(
+                m, &error,
+                DBUS_TYPE_INT32, &interface,
+                DBUS_TYPE_INT32, &protocol,
+                DBUS_TYPE_UINT32, &flags,
+                DBUS_TYPE_STRING, &name,
+                DBUS_TYPE_UINT16, &clazz,
+                DBUS_TYPE_UINT16, &type,
+                DBUS_TYPE_UINT32, &ttl,
+                DBUS_TYPE_INVALID) || !name ||
+                read_rdata (m, 7, &rdata, &size)) {
+            avahi_log_warn("Error parsing EntryGroup::AddRecord message");
+            goto fail;
+        }
+
+        if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
+
+        if (!avahi_is_valid_domain_name (name))
+            return respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL);
+
+        if (!(r = avahi_record_new_full (name, clazz, type, ttl)))
+            return respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL);
+
+        if (avahi_rdata_parse (r, rdata, size) < 0) {
+            avahi_record_unref (r);
+            return respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL);
+        }
+        
+        if (avahi_server_add(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, r) < 0) {
+            avahi_record_unref (r);
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
+        }
+
+        if (!(flags & AVAHI_PUBLISH_UPDATE))
+            i->n_entries ++;
+       
+        avahi_record_unref (r); 
+
         return respond_ok(c, m);
     } 
     
     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
 
@@ -1719,7 +1815,7 @@ fail:
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
-static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
+static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
     DBusError error;
 
     dbus_error_init(&error);
@@ -1904,7 +2000,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -1949,7 +2045,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -1994,7 +2090,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2044,7 +2140,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2099,7 +2195,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         }
 
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2155,7 +2251,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         }
 
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2204,7 +2300,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
         
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2262,7 +2358,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2322,7 +2418,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2377,7 +2473,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-        if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
@@ -2410,13 +2506,22 @@ fail:
 void dbus_protocol_server_state_changed(AvahiServerState state) {
     DBusMessage *m;
     int32_t t;
+    const char *e;
     
     if (!server)
         return;
 
     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
     t = (int32_t) state;
-    dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
+
+    if (state == AVAHI_SERVER_COLLISION)
+        e = AVAHI_DBUS_ERR_COLLISION;
+    else if (state == AVAHI_SERVER_FAILURE)
+        e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
+    else
+        e = AVAHI_DBUS_ERR_OK;
+    
+    dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID);
     dbus_connection_send(server->bus, m, NULL);
     dbus_message_unref(m);
 }