]> git.meshlink.io Git - catta/commitdiff
* add proper error codes and patch everything to make use of it
authorLennart Poettering <lennart@poettering.net>
Fri, 5 Aug 2005 18:59:21 +0000 (18:59 +0000)
committerLennart Poettering <lennart@poettering.net>
Fri, 5 Aug 2005 18:59:21 +0000 (18:59 +0000)
* parameter validity checkin in all user visible functions of libavahi-core
* two new python tools/examples avahi-resolve-host-name and avahi-resolve-address

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@238 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

29 files changed:
avahi-common/dbus.h
avahi-common/rr.c
avahi-common/rr.h
avahi-common/util.c
avahi-common/util.h
avahi-core/avahi-reflector.c
avahi-core/avahi-test.c
avahi-core/browse-dns-server.c
avahi-core/browse-domain.c
avahi-core/browse-service-type.c
avahi-core/browse-service.c
avahi-core/browse.c
avahi-core/conformance-test.c
avahi-core/core.h
avahi-core/resolve-address.c
avahi-core/resolve-host-name.c
avahi-core/resolve-service.c
avahi-core/server.c
avahi-core/server.h
avahi-daemon/dbus-protocol.c
avahi-daemon/main.c
avahi-daemon/static-services.c
avahi-discover-standalone/main.c
avahi-utils/Makefile.am
avahi-utils/avahi-resolve-address.in [new file with mode: 0755]
avahi-utils/avahi-resolve-host-name.in [new file with mode: 0755]
doxygen.cfg
examples/browse-services.c
examples/publish-service.c

index ddbd47a1f510d391b293bdf792364efad38b9349..64696d2760e0fa9f9a9b2dd7f315d5cf542ea0b0 100644 (file)
@@ -32,13 +32,25 @@ AVAHI_C_DECL_BEGIN
 #define AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER AVAHI_DBUS_NAME".ServiceTypeBrowser"
 #define AVAHI_DBUS_INTERFACE_SERVICE_BROWSER AVAHI_DBUS_NAME".ServiceBrowser"
 
-#define AVAHI_DBUS_ERROR_INVALID_SERVICE "org.freedesktop.Avahi.InvalidServiceError"
-#define AVAHI_DBUS_ERROR_INVALID_ADDRESS "org.freedesktop.Avahi.InvalidAddressError"
-#define AVAHI_DBUS_ERROR_TIMEOUT "org.freedesktop.Avahi.TimeoutError"
-#define AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS "org.freedesktop.Avahi.TooManyClientsError"
-#define AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS "org.freedesktop.Avahi.TooManyObjectsError"
-#define AVAHI_DBUS_ERROR_TOO_MANY_ENTRIES "org.freedesktop.Avahi.TooManyEntriesError"
-#define AVAHI_DBUS_ERROR_OS "org.freedesktop.Avahi.OSError"
+#define AVAHI_DBUS_ERR_FAILURE "org.freedesktop.Avahi.Failure"
+#define AVAHI_DBUS_ERR_BAD_STATE "org.freedesktop.Avahi.BadStateError"
+#define AVAHI_DBUS_ERR_INVALID_HOST_NAME "org.freedesktop.Avahi.InvalidHostNameError"
+#define AVAHI_DBUS_ERR_INVALID_DOMAIN_NAME "org.freedesktop.Avahi.InvalidDomainNameError"
+#define AVAHI_DBUS_ERR_NO_NETWORK "org.freedesktop.Avahi.NoNetworkError"
+#define AVAHI_DBUS_ERR_INVALID_TTL "org.freedesktop.Avahi.InvalidTTLError"
+#define AVAHI_DBUS_ERR_IS_PATTERN "org.freedesktop.Avahi.IsPatternError"
+#define AVAHI_DBUS_ERR_LOCAL_COLLISION "org.freedesktop.Avahi.LocalCollisionError"
+#define AVAHI_DBUS_ERR_INVALID_RECORD "org.freedesktop.Avahi.InvalidRecordError"
+#define AVAHI_DBUS_ERR_INVALID_SERVICE_NAME "org.freedesktop.Avahi.InvalidServiceNameError"
+#define AVAHI_DBUS_ERR_INVALID_SERVICE_TYPE "org.freedesktop.Avahi.InvalidServiceTypeError"
+#define AVAHI_DBUS_ERR_INVALID_PORT "org.freedesktop.Avahi.InvalidPortError"
+#define AVAHI_DBUS_ERR_INVALID_KEY "org.freedesktop.Avahi.InvalidKeyError"
+#define AVAHI_DBUS_ERR_INVALID_ADDRESS "org.freedesktop.Avahi.InvalidAddressError"
+#define AVAHI_DBUS_ERR_TIMEOUT "org.freedesktop.Avahi.TimeoutError"
+#define AVAHI_DBUS_ERR_TOO_MANY_CLIENTS "org.freedesktop.Avahi.TooManyClientsError"
+#define AVAHI_DBUS_ERR_TOO_MANY_OBJECTS "org.freedesktop.Avahi.TooManyObjectsError"
+#define AVAHI_DBUS_ERR_TOO_MANY_ENTRIES "org.freedesktop.Avahi.TooManyEntriesError"
+#define AVAHI_DBUS_ERR_OS "org.freedesktop.Avahi.OSError"
 
 AVAHI_C_DECL_END
 
index c510e7f4c510f442ee4dc49859e9b1a44a4cabc0..1a30146bbe68ddfede2ca83001ec5da5da7d5e54 100644 (file)
@@ -552,3 +552,49 @@ gboolean avahi_record_is_goodbye(AvahiRecord *r) {
 
     return r->ttl == 0;
 }
+
+gboolean avahi_key_valid(AvahiKey *k) {
+    g_assert(k);
+
+    if (!avahi_valid_domain_name(k->name))
+        return FALSE;
+    
+    return TRUE;
+}
+
+gboolean avahi_record_valid(AvahiRecord *r) {
+    g_assert(r);
+
+    if (!avahi_key_valid(r->key))
+        return FALSE;
+
+    switch (r->key->type) {
+
+        case AVAHI_DNS_TYPE_PTR:
+        case AVAHI_DNS_TYPE_CNAME:
+            return avahi_valid_domain_name(r->data.ptr.name);
+
+        case AVAHI_DNS_TYPE_SRV:
+            return avahi_valid_domain_name(r->data.srv.name);
+
+        case AVAHI_DNS_TYPE_HINFO:
+            return
+                strlen(r->data.hinfo.os) <= 255 &&
+                strlen(r->data.hinfo.cpu) <= 255;
+
+            
+        case AVAHI_DNS_TYPE_TXT: {
+
+            AvahiStringList *strlst;
+
+            for (strlst = r->data.txt.string_list; strlst; strlst = strlst->next)
+                if (strlst->size > 255)
+                    return FALSE;
+
+            return TRUE;
+        }
+    }
+            
+
+    return TRUE;
+}
index 25d6eee5a269d2c8ce421e21e0022ba307bf53a0..f5349e9fefed567fb6084e8e6c158bd6bb103233 100644 (file)
@@ -82,13 +82,11 @@ typedef struct  {
     guint32 ttl;     /**< DNS TTL of this record */
 
     union {
-
         
         struct {
             gpointer data;
             guint16 size;
         } generic; /**< Generic record data for unknown types */
-
         
         struct {
             guint16 priority;
@@ -200,6 +198,12 @@ gint avahi_record_lexicographical_compare(AvahiRecord *a, AvahiRecord *b);
 /** Return TRUE if the specified record is an mDNS goodbye record. i.e. TTL is zero. */
 gboolean avahi_record_is_goodbye(AvahiRecord *r);
 
+/** Check whether the specified key is valid */
+gboolean avahi_key_valid(AvahiKey *k);
+
+/** Check whether the specified record is valid */
+gboolean avahi_record_valid(AvahiRecord *r);
+
 AVAHI_C_DECL_END
 
 #endif
index 8be7b8830b90e4c856f2ab93878c77cadd7d5e22..a977bb2a04f144666b71735d72a5edc9d254e572 100644 (file)
@@ -414,3 +414,97 @@ gchar *avahi_format_mac_address(const guint8* mac, guint size) {
     *(--t) = 0;
     return r;
 }
+
+gboolean avahi_valid_service_type(const gchar *t) {
+    const gchar *p;
+    g_assert(t);
+
+    if (strlen(t) < 5)
+        return FALSE;
+    
+    if (*t != '_')
+        return FALSE;
+
+    if (!(p = strchr(t, '.')))
+        return FALSE;
+
+    if (p - t > 63 || p - t < 2)
+        return FALSE;
+
+    if (*(++p) != '_')
+        return FALSE;
+
+    if (strchr(p, '.'))
+        return FALSE;
+
+    if (strlen(p) > 63 || strlen(p) < 2)
+        return FALSE;
+    
+    return TRUE;
+}
+
+gboolean avahi_valid_domain_name(const gchar *t) {
+    const gchar *p, *dp;
+    gboolean dot = FALSE;
+        
+    g_assert(t);
+
+    if (*t == 0)
+        return FALSE;
+
+    /* Domains may not start with a dot */
+    if (*t == '.')
+        return FALSE;
+
+    dp = t; 
+
+    for (p = t; *p; p++) {
+
+        if (*p == '.') {
+            if (dot) /* Two subsequent dots */
+                return FALSE;
+
+            if (p - dp > 63)
+                return FALSE;
+
+            dot = TRUE;
+            dp = p + 1;
+        } else
+            dot = FALSE;
+
+    }
+
+    if (p - dp > 63)
+        return FALSE;
+
+    /* A trailing dot IS allowed */
+    
+    return TRUE;
+}
+
+gboolean avahi_valid_service_name(const gchar *t) {
+    g_assert(t);
+
+    if (*t == 0)
+        return FALSE;
+
+    if (strlen(t) > 63)
+        return FALSE;
+
+    return TRUE;
+}
+
+gboolean avahi_valid_host_name(const gchar *t) {
+    g_assert(t);
+
+    if (*t == 0)
+        return FALSE;
+
+    if (strlen(t) > 63)
+        return FALSE;
+
+    if (strchr(t, '.'))
+        return FALSE;
+
+    return TRUE;
+}
index 731a5a13acecd03a5f1954d287a54691b0f03800..0d4fb4b95df3708e87fd4ae56f0d33ac92de4cfa 100644 (file)
@@ -60,6 +60,11 @@ guint avahi_domain_hash(const gchar *s);
 
 gchar *avahi_format_mac_address(const guint8* mac, guint size);
 
+gboolean avahi_valid_service_type(const gchar *t);
+gboolean avahi_valid_domain_name(const gchar *t);
+gboolean avahi_valid_service_name(const gchar *t);
+gboolean avahi_valid_host_name(const gchar *t);
+
 AVAHI_C_DECL_END
 
 #endif
index 7af0dd40aa0541276ef8f2cc923b2e1d3de1bdd3..0a91b87bf73b48f5e31eaad3bf5366bd4e4300fc 100644 (file)
@@ -34,6 +34,7 @@ int main(int argc, char*argv[]) {
     AvahiServer *server;
     AvahiServerConfig config;
     GMainLoop *loop;
+    gint error;
 
     avahi_server_config_init(&config);
     config.publish_hinfo = FALSE;
@@ -43,7 +44,7 @@ int main(int argc, char*argv[]) {
     config.use_ipv6 = FALSE;
     config.enable_reflector = TRUE;
     
-    server = avahi_server_new(NULL, &config, NULL, NULL);
+    server = avahi_server_new(NULL, &config, NULL, NULL, &error);
     avahi_server_config_free(&config);
 
     loop = g_main_loop_new(NULL, FALSE);
index cc950d46e441672d785b21b4e0d85786d14afeef..5db2473d327bf16af5cb5df1175a6c7183debec7 100644 (file)
@@ -217,10 +217,11 @@ int main(int argc, char *argv[]) {
     AvahiServiceBrowser *sb;
     AvahiServiceResolver *sr;
     AvahiDNSServerBrowser *dsb;
+    gint error;
     
     avahi_server_config_init(&config);
 /*     config.host_name = g_strdup("test"); */
-    server = avahi_server_new(NULL, &config, server_callback, NULL);
+    server = avahi_server_new(NULL, &config, server_callback, NULL, &error);
     avahi_server_config_free(&config);
 
     k = avahi_key_new("_http._tcp.local", AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
index f8e8f304015b7b19d26644d42f5e35669da9fda4..057f3e3bfb4899989706c18295b671b3f593a396 100644 (file)
@@ -157,15 +157,21 @@ AvahiDNSServerBrowser *avahi_dns_server_browser_new(AvahiServer *server, AvahiIf
     g_assert(callback);
     g_assert(type == AVAHI_DNS_SERVER_RESOLVE || type == AVAHI_DNS_SERVER_UPDATE);
 
+    if (domain && !avahi_valid_domain_name(domain)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
+        return NULL;
+    }
+    
     b = g_new(AvahiDNSServerBrowser, 1);
     b->server = server;
-    b->domain_name = avahi_normalize_name(domain ? domain : "local.");
+    b->domain_name = avahi_normalize_name(domain ? domain : "local");
     b->callback = callback;
     b->userdata = userdata;
     b->aprotocol = aprotocol;
     b->n_info = 0;
 
     AVAHI_LLIST_HEAD_INIT(AvahiDNSServerInfo, b->info);
+    AVAHI_LLIST_PREPEND(AvahiDNSServerBrowser, browser, server->dns_server_browsers, b);
     
     n = g_strdup_printf("%s.%s",type == AVAHI_DNS_SERVER_RESOLVE ? "_domain._udp" : "_dns-update._udp", b->domain_name);
     k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
@@ -174,7 +180,10 @@ AvahiDNSServerBrowser *avahi_dns_server_browser_new(AvahiServer *server, AvahiIf
     b->record_browser = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, b);
     avahi_key_unref(k);
 
-    AVAHI_LLIST_PREPEND(AvahiDNSServerBrowser, browser, server->dns_server_browsers, b);
+    if (!b->record_browser) {
+        avahi_dns_server_browser_free(b);
+        return NULL;
+    }
     
     return b;
 }
@@ -187,7 +196,8 @@ void avahi_dns_server_browser_free(AvahiDNSServerBrowser *b) {
     
     AVAHI_LLIST_REMOVE(AvahiDNSServerBrowser, browser, b->server->dns_server_browsers, b);
 
-    avahi_record_browser_free(b->record_browser);
+    if (b->record_browser)
+        avahi_record_browser_free(b->record_browser);
     g_free(b->domain_name);
     g_free(b);
 }
index c6331b4c20681a2a4064301f430a2d51796bbcf5..de3cb1bfea2bbd7a1ca8ddcc803a48450397a4fd 100644 (file)
@@ -60,6 +60,12 @@ AvahiDomainBrowser *avahi_domain_browser_new(AvahiServer *server, AvahiIfIndex i
     
     g_assert(server);
     g_assert(callback);
+    g_assert(type >= AVAHI_DOMAIN_BROWSER_BROWSE && type <= AVAHI_DOMAIN_BROWSER_BROWSE_LEGACY);
+
+    if (domain && !avahi_valid_domain_name(domain)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
+        return NULL;
+    }
 
     b = g_new(AvahiDomainBrowser, 1);
     b->server = server;
@@ -67,6 +73,8 @@ AvahiDomainBrowser *avahi_domain_browser_new(AvahiServer *server, AvahiIfIndex i
     b->callback = callback;
     b->userdata = userdata;
 
+    AVAHI_LLIST_PREPEND(AvahiDomainBrowser, browser, server->domain_browsers, b);
+
     switch (type) {
         case AVAHI_DOMAIN_BROWSER_BROWSE:
             n = g_strdup_printf("b._dns-sd._udp.%s", b->domain_name);
@@ -97,7 +105,10 @@ AvahiDomainBrowser *avahi_domain_browser_new(AvahiServer *server, AvahiIfIndex i
     b->record_browser = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, b);
     avahi_key_unref(k);
 
-    AVAHI_LLIST_PREPEND(AvahiDomainBrowser, browser, server->domain_browsers, b);
+    if (!b->record_browser) {
+        avahi_domain_browser_free(b);
+        return NULL;
+    }
     
     return b;
 }
@@ -107,7 +118,9 @@ void avahi_domain_browser_free(AvahiDomainBrowser *b) {
 
     AVAHI_LLIST_REMOVE(AvahiDomainBrowser, browser, b->server->domain_browsers, b);
 
-    avahi_record_browser_free(b->record_browser);
+    if (b->record_browser)
+        avahi_record_browser_free(b->record_browser);
+    
     g_free(b->domain_name);
     g_free(b);
 }
index 7cd6cf76ebc725730a33eb90cd0350b2530eab4c..3534b6fa9d529d238b1d2cd95eed45ebb46c7bb6 100644 (file)
@@ -90,12 +90,18 @@ AvahiServiceTypeBrowser *avahi_service_type_browser_new(AvahiServer *server, gin
     g_assert(server);
     g_assert(callback);
 
+    if (domain && !avahi_valid_domain_name(domain)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
+        return NULL;
+    }
+
     b = g_new(AvahiServiceTypeBrowser, 1);
     b->server = server;
     b->domain_name = avahi_normalize_name(domain ? domain : "local");
     b->callback = callback;
     b->userdata = userdata;
 
+    AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, browser, server->service_type_browsers, b);
 
     n = g_strdup_printf("_services._dns-sd._udp.%s", b->domain_name);
     k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
@@ -104,7 +110,8 @@ AvahiServiceTypeBrowser *avahi_service_type_browser_new(AvahiServer *server, gin
     b->record_browser = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, b);
     avahi_key_unref(k);
 
-    AVAHI_LLIST_PREPEND(AvahiServiceTypeBrowser, browser, server->service_type_browsers, b);
+    if (!b->record_browser)
+        return NULL;
     
     return b;
 }
@@ -114,7 +121,9 @@ void avahi_service_type_browser_free(AvahiServiceTypeBrowser *b) {
 
     AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, browser, b->server->service_type_browsers, b);
 
-    avahi_record_browser_free(b->record_browser);
+    if (b->record_browser)
+        avahi_record_browser_free(b->record_browser);
+    
     g_free(b->domain_name);
     g_free(b);
 }
index f72ce6c3440637c4fcdeb46c905af800c8943dce..34a2536f47903870fcc2ecc3e7ddc01b1f84f133 100644 (file)
@@ -93,21 +93,36 @@ AvahiServiceBrowser *avahi_service_browser_new(AvahiServer *server, AvahiIfIndex
     g_assert(callback);
     g_assert(service_type);
 
+    if (!avahi_valid_service_type(service_type)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_TYPE);
+        return NULL;
+    }
+
+    if (domain && !avahi_valid_domain_name(domain)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
+        return NULL;
+    }
+
     b = g_new(AvahiServiceBrowser, 1);
     b->server = server;
     b->domain_name = avahi_normalize_name(domain ? domain : "local");
     b->service_type = avahi_normalize_name(service_type);
     b->callback = callback;
     b->userdata = userdata;
+    AVAHI_LLIST_PREPEND(AvahiServiceBrowser, browser, server->service_browsers, b);
 
     n = g_strdup_printf("%s.%s", b->service_type, b->domain_name);
     k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
     g_free(n);
     
     b->record_browser = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, b);
+
     avahi_key_unref(k);
 
-    AVAHI_LLIST_PREPEND(AvahiServiceBrowser, browser, server->service_browsers, b);
+    if (!b->record_browser) {
+        avahi_service_browser_free(b);
+        return NULL;
+    }
     
     return b;
 }
@@ -117,7 +132,9 @@ void avahi_service_browser_free(AvahiServiceBrowser *b) {
 
     AVAHI_LLIST_REMOVE(AvahiServiceBrowser, browser, b->server->service_browsers, b);
 
-    avahi_record_browser_free(b->record_browser);
+    if (b->record_browser)
+        avahi_record_browser_free(b->record_browser);
+    
     g_free(b->domain_name);
     g_free(b->service_type);
     g_free(b);
index 5f4d216be74ecf728460421a25432d40031886e9..5885cb4fb2152161969e8f7ddab5724abda1c012 100644 (file)
@@ -124,7 +124,15 @@ AvahiRecordBrowser *avahi_record_browser_new(AvahiServer *server, AvahiIfIndex i
     g_assert(key);
     g_assert(callback);
 
-    g_assert(!avahi_key_is_pattern(key));
+    if (avahi_key_is_pattern(key)) {
+        avahi_server_set_errno(server, AVAHI_ERR_IS_PATTERN);
+        return NULL;
+    }
+
+    if (!avahi_key_valid(key)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_KEY);
+        return NULL;
+    }
     
     b = g_new(AvahiRecordBrowser, 1);
     b->dead = FALSE;
index ccc9a12219f426fbaa73d8720e6f6a701de3895c..13704c355950d76d2bd15ce75df46935c1aa3243 100644 (file)
@@ -101,8 +101,9 @@ static void server_callback(AvahiServer *s, AvahiServerState state, gpointer use
 
 int main(int argc, char *argv[]) {
     GMainLoop *loop = NULL;
+    gint error;
 
-    avahi = avahi_server_new(NULL, NULL, server_callback, NULL);
+    avahi = avahi_server_new(NULL, NULL, server_callback, NULL, &error);
     
     loop = g_main_loop_new(NULL, FALSE);
     g_timeout_add(1000*5, dump_timeout, avahi);
index 25e9c0a7fa088eb1ad3aacb7d55541e40cf267cb..1adf244e8a98a4e47349766db736969a2317e0a8 100644 (file)
@@ -35,7 +35,9 @@
 
 #include <avahi-common/cdecl.h>
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
 AVAHI_C_DECL_BEGIN
+#endif
 
 /** An mDNS responder object */
 typedef struct AvahiServer AvahiServer;
@@ -46,19 +48,42 @@ typedef struct AvahiEntry AvahiEntry;
 /** A group of locally registered DNS RRs */
 typedef struct AvahiEntryGroup AvahiEntryGroup;
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
 AVAHI_C_DECL_END
+#endif
 
 #include <avahi-common/address.h>
 #include <avahi-common/rr.h>
 #include <avahi-common/alternative.h>
 
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
 AVAHI_C_DECL_BEGIN
+#endif
 
 /** Error codes used by avahi */
 enum { 
-    AVAHI_OK = 0,                      /**< OK */
-    AVAHI_ERR_FAILURE = -1,            /**< Generic error code */
-    AVAHI_ERR_BAD_STATE = -2           /**< Object was in a bad state */
+    AVAHI_OK = 0,                          /**< OK */
+    AVAHI_ERR_FAILURE = -1,                /**< Generic error code */
+    AVAHI_ERR_BAD_STATE = -2,              /**< Object was in a bad state */
+    AVAHI_ERR_INVALID_HOST_NAME = -3,      /**< Invalid host name */
+    AVAHI_ERR_INVALID_DOMAIN_NAME = -4,    /**< Invalid domain name */
+    AVAHI_ERR_NO_NETWORK = -5,             /**< No suitable network protocol available */
+    AVAHI_ERR_INVALID_TTL = -6,            /**< Invalid DNS TTL */
+    AVAHI_ERR_IS_PATTERN = -7,             /**< RR key is pattern */
+    AVAHI_ERR_LOCAL_COLLISION = -8,        /**< Local name collision */
+    AVAHI_ERR_INVALID_RECORD = -9,         /**< Invalid RR */
+    AVAHI_ERR_INVALID_SERVICE_NAME = -10,  /**< Invalid service name */
+    AVAHI_ERR_INVALID_SERVICE_TYPE = -11,  /**< Invalid service type */
+    AVAHI_ERR_INVALID_PORT = -12,          /**< Invalid port number */
+    AVAHI_ERR_INVALID_KEY = -13,           /**< Invalid key */
+    AVAHI_ERR_INVALID_ADDRESS = -14,       /**< Invalid address */
+    AVAHI_ERR_TIMEOUT = -15,               /**< Timeout reached */
+    AVAHI_ERR_TOO_MANY_CLIENTS = -16,      /**< Too many clients */
+    AVAHI_ERR_TOO_MANY_OBJECTS = -17,      /**< Too many objects */
+    AVAHI_ERR_TOO_MANY_ENTRIES = -18,      /**< Too many entries */
+    AVAHI_ERR_OS = -19,                    /**< OS error */
+    AVAHI_ERR_ACCESS_DENIED = -20,         /**< Access denied */
+    AVAHI_ERR_MAX = -21
 };
 
 /** States of a server object */
@@ -113,7 +138,8 @@ AvahiServer *avahi_server_new(
     GMainContext *c,               /**< The GLIB main loop context to attach to */
     const AvahiServerConfig *sc,   /**< If non-NULL a pointer to a configuration structure for the server. The server makes an internal deep copy of this structure, so you may free it using avahi_server_config_done() immediately after calling this function. */
     AvahiServerCallback callback,  /**< A callback which is called whenever the state of the server changes */
-    gpointer userdata              /**< An opaque pointer which is passed to the callback function */);
+    gpointer userdata,             /**< An opaque pointer which is passed to the callback function */
+    gint *error);
 
 /** Free an mDNS responder object */
 void avahi_server_free(AvahiServer* s);
@@ -603,6 +629,14 @@ AvahiDNSServerBrowser *avahi_dns_server_browser_new(
 /** Free an AvahiDNSServerBrowser object */
 void avahi_dns_server_browser_free(AvahiDNSServerBrowser *b);
 
+/** Return a human readable error string for the specified error code */
+const gchar *avahi_strerror(gint error);
+
+/** Return the last error code */
+gint avahi_server_errno(AvahiServer *s);
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
 AVAHI_C_DECL_END
+#endif
 
 #endif
index d315ac9206ad3908b8e5df1afaceba77f612aa51..89f9bcfa64c86ead9069cf945e81da546b5bacdb 100644 (file)
@@ -111,6 +111,11 @@ AvahiAddressResolver *avahi_address_resolver_new(AvahiServer *server, AvahiIfInd
     
     r->record_browser = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
     avahi_key_unref(k);
+
+    if (!r->record_browser) {
+        avahi_address_resolver_free(r);
+        return NULL;
+    }
     
     return r;
 }
index 0ab2e73fbdcb1f80960d1041103afe8a072889f1..c18722d19dc59b1b09a8749e12b34025387bfc91 100644 (file)
@@ -115,6 +115,11 @@ AvahiHostNameResolver *avahi_host_name_resolver_new(AvahiServer *server, AvahiIf
 
     g_assert(aprotocol == AVAHI_PROTO_UNSPEC || aprotocol == AVAHI_PROTO_INET || aprotocol == AVAHI_PROTO_INET6);
 
+    if (!avahi_valid_domain_name(host_name)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_HOST_NAME);
+        return NULL;
+    }
+    
     r = g_new(AvahiHostNameResolver, 1);
     r->server = server;
     r->host_name = avahi_normalize_name(host_name);
@@ -127,20 +132,34 @@ AvahiHostNameResolver *avahi_host_name_resolver_new(AvahiServer *server, AvahiIf
     r->time_event = avahi_time_event_queue_add(server->time_event_queue, &tv, time_event_callback, r);
 
     AVAHI_LLIST_PREPEND(AvahiHostNameResolver, resolver, server->host_name_resolvers, r);
+
+    r->record_browser_aaaa = r->record_browser_a = NULL;
     
     if (aprotocol == AVAHI_PROTO_INET || aprotocol == AVAHI_PROTO_UNSPEC) {
         k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A);
         r->record_browser_a = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
         avahi_key_unref(k);
+
+        if (!r->record_browser_a)
+            goto fail;
     } 
 
     if (aprotocol == AVAHI_PROTO_INET6 || aprotocol == AVAHI_PROTO_UNSPEC) {
         k = avahi_key_new(host_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA);
         r->record_browser_aaaa = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
         avahi_key_unref(k);
+
+        if (!r->record_browser_aaaa)
+            goto fail;
     }
-    
+
+    g_assert(r->record_browser_aaaa || r->record_browser_a);
+
     return r;
+
+fail:
+    avahi_host_name_resolver_free(r);
+    return NULL;
 }
 
 void avahi_host_name_resolver_free(AvahiHostNameResolver *r) {
index b15af4f25232d826241e22b9d0a91d6d68bdbc0c..2ad38f89ea26114ae9154d03200784fb8fc7a17c 100644 (file)
@@ -206,6 +206,21 @@ AvahiServiceResolver *avahi_service_resolver_new(AvahiServer *server, AvahiIfInd
 
     g_assert(aprotocol == AVAHI_PROTO_UNSPEC || aprotocol == AVAHI_PROTO_INET || aprotocol == AVAHI_PROTO_INET6);
 
+    if (!avahi_valid_service_name(name)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_NAME);
+        return NULL;
+    }
+
+    if (!avahi_valid_service_type(type)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_TYPE);
+        return NULL;
+    }
+
+    if (!avahi_valid_domain_name(domain)) {
+        avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
+        return NULL;
+    }
+    
     r = g_new(AvahiServiceResolver, 1);
     r->server = server;
     r->service_name = g_strdup(name);
@@ -234,10 +249,20 @@ AvahiServiceResolver *avahi_service_resolver_new(AvahiServer *server, AvahiIfInd
     r->record_browser_srv = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
     avahi_key_unref(k);
 
+    if (!r->record_browser_srv) {
+        avahi_service_resolver_free(r);
+        return NULL;
+    }
+    
     k = avahi_key_new(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT);
     r->record_browser_txt = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
     avahi_key_unref(k);
-    
+
+    if (!r->record_browser_txt) {
+        avahi_service_resolver_free(r);
+        return NULL;
+    }
+
     return r;
 }
 
index 3c385070b20e23bd8b95213eee4992eef3750d97..c4acf35db1e1544417e6df52d1510bbaac7844d9 100644 (file)
@@ -259,6 +259,7 @@ static void incoming_probe(AvahiServer *s, AvahiRecord *record, AvahiInterface *
         }
     }
 
+
     if (!ours) {
 
         if (won)
@@ -1221,6 +1222,9 @@ gint avahi_server_set_host_name(AvahiServer *s, const gchar *host_name) {
     g_assert(s);
     g_assert(host_name);
 
+    if (host_name && !avahi_valid_host_name(host_name))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
+
     withdraw_host_rrs(s);
 
     g_free(s->host_name);
@@ -1236,6 +1240,9 @@ gint avahi_server_set_domain_name(AvahiServer *s, const gchar *domain_name) {
     g_assert(s);
     g_assert(domain_name);
 
+    if (domain_name && !avahi_valid_domain_name(domain_name))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME);
+
     withdraw_host_rrs(s);
 
     g_free(s->domain_name);
@@ -1257,8 +1264,20 @@ static void prepare_pollfd(AvahiServer *s, GPollFD *pollfd, gint fd) {
     g_source_add_poll(s->source, pollfd);
 }
 
-AvahiServer *avahi_server_new(GMainContext *c, const AvahiServerConfig *sc, AvahiServerCallback callback, gpointer userdata) {
+static gint valid_server_config(const AvahiServerConfig *sc) {
+
+    if (sc->host_name && !avahi_valid_host_name(sc->host_name))
+        return AVAHI_ERR_INVALID_HOST_NAME;
+    
+    if (sc->domain_name && !avahi_valid_domain_name(sc->domain_name))
+        return AVAHI_ERR_INVALID_DOMAIN_NAME;
+
+    return AVAHI_OK;
+}
+
+AvahiServer *avahi_server_new(GMainContext *c, const AvahiServerConfig *sc, AvahiServerCallback callback, gpointer userdata, gint *error) {
     AvahiServer *s;
+    gint e;
     
     static GSourceFuncs source_funcs = {
         prepare_func,
@@ -1269,6 +1288,12 @@ AvahiServer *avahi_server_new(GMainContext *c, const AvahiServerConfig *sc, Avah
         NULL
     };
 
+    if ((e = valid_server_config(sc)) < 0) {
+        if (error)
+            *error = e;
+        return NULL;
+    }
+    
     s = g_new(AvahiServer, 1);
     s->n_host_rr_pending = 0;
     s->need_entry_cleanup = s->need_group_cleanup = s->need_browser_cleanup = FALSE;
@@ -1282,9 +1307,12 @@ AvahiServer *avahi_server_new(GMainContext *c, const AvahiServerConfig *sc, Avah
     s->fd_ipv6 = s->config.use_ipv6 ? avahi_open_socket_ipv6() : -1;
     
     if (s->fd_ipv6 < 0 && s->fd_ipv4 < 0) {
-        g_critical("Selected neither IPv6 nor IPv4 support, aborting.\n");
         avahi_server_config_free(&s->config);
         g_free(s);
+
+        if (error)
+            *error = AVAHI_ERR_NO_NETWORK;
+        
         return NULL;
     }
 
@@ -1354,6 +1382,8 @@ AvahiServer *avahi_server_new(GMainContext *c, const AvahiServerConfig *sc, Avah
     s->hinfo_entry_group = NULL;
     s->browse_domain_entry_group = NULL;
     register_stuff(s);
+
+    s->error = AVAHI_OK;
     
     return s;
 }
@@ -1461,13 +1491,16 @@ gint avahi_server_add(
     g_assert(r);
 
     if (r->ttl == 0)
-        return -1;
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_TTL);
 
     if (avahi_key_is_pattern(r->key))
-        return -1;
+        return avahi_server_set_errno(s, AVAHI_ERR_IS_PATTERN);
+
+    if (!avahi_record_valid(r))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_RECORD);
 
     if (check_record_conflict(s, interface, protocol, r, flags) < 0)
-        return -1;
+        return avahi_server_set_errno(s, AVAHI_ERR_LOCAL_COLLISION);
 
     e = g_new(AvahiEntry, 1);
     e->server = s;
@@ -1551,6 +1584,7 @@ gint avahi_server_add_ptr(
     AvahiRecord *r;
     gint ret;
 
+    g_assert(s);
     g_assert(dest);
 
     r = avahi_record_new_full(name ? name : s->host_name_fqdn, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR, ttl);
@@ -1570,11 +1604,16 @@ gint avahi_server_add_address(
     AvahiAddress *a) {
 
     gchar *n = NULL;
-    gint ret = 0;
+    gint ret = AVAHI_OK;
     g_assert(s);
     g_assert(a);
 
     name = name ? (n = avahi_normalize_name(name)) : s->host_name_fqdn;
+
+    if (!avahi_valid_domain_name(name)) {
+        avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
+        goto fail;
+    }
     
     if (a->family == AVAHI_PROTO_INET) {
         gchar *reverse;
@@ -1584,11 +1623,14 @@ gint avahi_server_add_address(
         r->data.a.address = a->data.ipv4;
         ret = avahi_server_add(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE | AVAHI_ENTRY_ALLOWMUTIPLE, r);
         avahi_record_unref(r);
+
+        if (ret < 0)
+            goto fail;
         
         reverse = avahi_reverse_lookup_name_ipv4(&a->data.ipv4);
-        ret |= avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name);
+        ret = avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name);
         g_free(reverse);
-        
+
     } else {
         gchar *reverse;
         AvahiRecord *r;
@@ -1598,14 +1640,22 @@ gint avahi_server_add_address(
         ret = avahi_server_add(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE | AVAHI_ENTRY_ALLOWMUTIPLE, r);
         avahi_record_unref(r);
 
+        if (ret < 0)
+            goto fail;
+
         reverse = avahi_reverse_lookup_name_ipv6_arpa(&a->data.ipv6);
-        ret |= avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name);
+        ret = avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name);
         g_free(reverse);
+
+        if (ret < 0)
+            goto fail;
     
         reverse = avahi_reverse_lookup_name_ipv6_int(&a->data.ipv6);
-        ret |= avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name);
+        ret = avahi_server_add_ptr(s, g, interface, protocol, flags | AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL_HOST_NAME, reverse, name);
         g_free(reverse);
     }
+
+fail:
     
     g_free(n);
 
@@ -1645,6 +1695,8 @@ gint avahi_server_add_txt_strlst(
     const gchar *name,
     AvahiStringList *strlst) {
 
+    g_assert(s);
+
     return server_add_txt_strlst_nocopy(s, g, interface, protocol, flags, ttl, name, avahi_string_list_copy(strlst));
 }
 
@@ -1721,19 +1773,31 @@ static gint server_add_service_strlst_nocopy(
 
     gchar ptr_name[256], svc_name[256], ename[64], enum_ptr[256];
     gchar *t, *d;
-    AvahiRecord *r;
+    AvahiRecord *r = NULL;
     gint ret = 0;
     
     g_assert(s);
     g_assert(type);
     g_assert(name);
 
+    if (!avahi_valid_service_name(name))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_SERVICE_NAME);
+
+    if (!avahi_valid_service_type(type))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_SERVICE_TYPE);
+
+    if (domain && !avahi_valid_domain_name(domain))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME);
+
+    if (host && !avahi_valid_domain_name(host))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_HOST_NAME);
+
+    if (port == 0)
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PORT);
+    
     escape_service_name(ename, sizeof(ename), name);
 
-    if (domain) {
-        while (domain[0] == '.')
-            domain++;
-    } else
+    if (!domain)
         domain = s->domain_name;
 
     if (!host)
@@ -1745,23 +1809,35 @@ static gint server_add_service_strlst_nocopy(
     g_snprintf(ptr_name, sizeof(ptr_name), "%s.%s", t, d);
     g_snprintf(svc_name, sizeof(svc_name), "%s.%s.%s", ename, t, d);
 
-    ret = avahi_server_add_ptr(s, g, interface, protocol, AVAHI_ENTRY_NULL, AVAHI_DEFAULT_TTL, ptr_name, svc_name);
+    if ((ret = avahi_server_add_ptr(s, g, interface, protocol, AVAHI_ENTRY_NULL, AVAHI_DEFAULT_TTL, ptr_name, svc_name)) < 0)
+        goto fail;
 
     r = avahi_record_new_full(svc_name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV, AVAHI_DEFAULT_TTL_HOST_NAME);
     r->data.srv.priority = 0;
     r->data.srv.weight = 0;
     r->data.srv.port = port;
     r->data.srv.name = avahi_normalize_name(host);
-    ret |= avahi_server_add(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE, r);
+    ret = avahi_server_add(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE, r);
     avahi_record_unref(r);
 
-    ret |= server_add_txt_strlst_nocopy(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL, svc_name, strlst);
+    if (ret < 0)
+        goto fail;
+
+    ret = server_add_txt_strlst_nocopy(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE, AVAHI_DEFAULT_TTL, svc_name, strlst);
+    strlst = NULL;
+
+    if (ret < 0)
+        goto fail;
 
     g_snprintf(enum_ptr, sizeof(enum_ptr), "_services._dns-sd._udp.%s", d);
-    ret |=avahi_server_add_ptr(s, g, interface, protocol, AVAHI_ENTRY_NULL, AVAHI_DEFAULT_TTL, enum_ptr, ptr_name);
+    ret avahi_server_add_ptr(s, g, interface, protocol, AVAHI_ENTRY_NULL, AVAHI_DEFAULT_TTL, enum_ptr, ptr_name);
 
+fail:
+    
     g_free(d);
     g_free(t);
+
+    avahi_string_list_free(strlst);
     
     return ret;
 }
@@ -1778,6 +1854,10 @@ gint avahi_server_add_service_strlst(
     guint16 port,
     AvahiStringList *strlst) {
 
+    g_assert(s);
+    g_assert(type);
+    g_assert(name);
+
     return server_add_service_strlst_nocopy(s, g, interface, protocol, name, type, domain, host, port, avahi_string_list_copy(strlst));
 }
 
@@ -1866,6 +1946,12 @@ gint avahi_server_add_dns_server_address(
     g_assert(type == AVAHI_DNS_SERVER_UPDATE || type == AVAHI_DNS_SERVER_RESOLVE);
     g_assert(address->family == AVAHI_PROTO_INET || address->family == AVAHI_PROTO_INET6);
 
+    if (domain && !avahi_valid_domain_name(domain))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME);
+
+    if (port == 0)
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PORT);
+    
     if (address->family == AVAHI_PROTO_INET) {
         hexstring(n+3, sizeof(n)-3, &address->data, 4);
         r = avahi_record_new_full(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A, AVAHI_DEFAULT_TTL_HOST_NAME);
@@ -1878,10 +1964,11 @@ gint avahi_server_add_dns_server_address(
     
     ret = avahi_server_add(s, g, interface, protocol, AVAHI_ENTRY_UNIQUE | AVAHI_ENTRY_ALLOWMUTIPLE, r);
     avahi_record_unref(r);
-    
-    ret |= avahi_server_add_dns_server_name(s, g, interface, protocol, domain, type, n, port);
 
-    return ret;
+    if (ret < 0)
+        return ret;
+    
+    return avahi_server_add_dns_server_name(s, g, interface, protocol, domain, type, n, port);
 }
 
 gint avahi_server_add_dns_server_name(
@@ -1902,10 +1989,13 @@ gint avahi_server_add_dns_server_name(
     g_assert(name);
     g_assert(type == AVAHI_DNS_SERVER_UPDATE || type == AVAHI_DNS_SERVER_RESOLVE);
 
-    if (domain) {
-        while (domain[0] == '.')
-            domain++;
-    } else
+    if (domain && !avahi_valid_domain_name(domain))
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_DOMAIN_NAME);
+
+    if (port == 0)
+        return avahi_server_set_errno(s, AVAHI_ERR_INVALID_PORT);
+    
+    if (!domain)
         domain = s->domain_name;
 
     d = avahi_normalize_name(domain);
@@ -1946,6 +2036,8 @@ void avahi_entry_group_change_state(AvahiEntryGroup *g, AvahiEntryGroupState sta
     if (g->state == state)
         return;
 
+    g_assert(state >= AVAHI_ENTRY_GROUP_UNCOMMITED && state <= AVAHI_ENTRY_GROUP_COLLISION);
+
     g->state = state;
     
     if (g->callback)
@@ -2031,7 +2123,7 @@ gint avahi_entry_group_commit(AvahiEntryGroup *g) {
     g_assert(!g->dead);
 
     if (g->state != AVAHI_ENTRY_GROUP_UNCOMMITED && g->state != AVAHI_ENTRY_GROUP_COLLISION)
-        return AVAHI_ERR_BAD_STATE;
+        return avahi_server_set_errno(g->server, AVAHI_ERR_BAD_STATE);
 
     g->n_register_try++;
 
@@ -2201,3 +2293,47 @@ AvahiServerConfig* avahi_server_config_copy(AvahiServerConfig *ret, const AvahiS
 
     return ret;
 }
+
+const gchar *avahi_strerror(gint error) {
+    g_assert(-error >= 0 && -error < -AVAHI_ERR_MAX);
+
+    const gchar * const msg[- AVAHI_ERR_MAX] = {
+        "OK",
+        "Operation failed",
+        "Bad state",
+        "Invalid host name",
+        "Invalid domain name",
+        "No suitable network protocol available",
+        "Invalid DNS TTL",
+        "Resource record key is pattern",
+        "Local name collision",
+        "Invalid record",
+        "Invalid service name",
+        "Invalid service type",
+        "Invalid port number",
+        "Invalid record key",
+        "Invalid address",
+        "Timeout reached",
+        "Too many clients",
+        "Too many objects",
+        "Too many entries",
+        "OS Error",
+        "Access denied"
+    };
+
+    return msg[-error];
+}
+
+gint avahi_server_errno(AvahiServer *s) {
+    g_assert(s);
+    
+    return s->error;
+}
+
+/* Just for internal use */
+gint avahi_server_set_errno(AvahiServer *s, gint error) {
+    g_assert(s);
+
+    return s->error = error;
+}
+
index 7049f58970077097e3ab74fe07eb075a4e39a789..6572fbb69e9983ade674cf7d3cf4113be455274c 100644 (file)
@@ -131,6 +131,8 @@ struct AvahiServer {
     /* Used for reflection of legacy unicast packets */
     AvahiLegacyUnicastReflectSlot **legacy_unicast_reflect_slots;
     guint16 legacy_unicast_reflect_id;
+
+    gint error;
 };
 
 gboolean avahi_server_entry_match_interface(AvahiEntry *e, AvahiInterface *i);
@@ -152,4 +154,6 @@ void avahi_host_rr_entry_group_callback(AvahiServer *s, AvahiEntryGroup *g, Avah
 void avahi_server_decrease_host_rr_pending(AvahiServer *s);
 void avahi_server_increase_host_rr_pending(AvahiServer *s);
 
+gint avahi_server_set_errno(AvahiServer *s, gint error);
+
 #endif
index 311d6640feef717816593d5827fd24dde3f34efa..a87712d88132c72103f5232b16afcb5661eae320 100644 (file)
@@ -319,10 +319,37 @@ static Client *client_get(const gchar *name, gboolean create) {
     return client;
 }
 
-static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, const gchar *error, const gchar *text) {
+static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, gint error, const gchar *text) {
     DBusMessage *reply;
 
-    reply = dbus_message_new_error(m, error, text);
+    const gchar * const table[- AVAHI_ERR_MAX] = {
+        NULL, /* OK */
+        AVAHI_DBUS_ERR_FAILURE,
+        AVAHI_DBUS_ERR_BAD_STATE,
+        AVAHI_DBUS_ERR_INVALID_HOST_NAME,
+        AVAHI_DBUS_ERR_INVALID_DOMAIN_NAME,
+        AVAHI_DBUS_ERR_NO_NETWORK,
+        AVAHI_DBUS_ERR_INVALID_TTL,
+        AVAHI_DBUS_ERR_IS_PATTERN,
+        AVAHI_DBUS_ERR_LOCAL_COLLISION,
+        AVAHI_DBUS_ERR_INVALID_RECORD,
+        AVAHI_DBUS_ERR_INVALID_SERVICE_NAME,
+        AVAHI_DBUS_ERR_INVALID_SERVICE_TYPE,
+        AVAHI_DBUS_ERR_INVALID_PORT,
+        AVAHI_DBUS_ERR_INVALID_KEY,
+        AVAHI_DBUS_ERR_INVALID_ADDRESS,
+        AVAHI_DBUS_ERR_TIMEOUT,
+        AVAHI_DBUS_ERR_TOO_MANY_CLIENTS,
+        AVAHI_DBUS_ERR_TOO_MANY_OBJECTS,
+        AVAHI_DBUS_ERR_TOO_MANY_ENTRIES,
+        AVAHI_DBUS_ERR_OS,
+        DBUS_ERROR_ACCESS_DENIED
+    };
+
+    g_assert(-error > -AVAHI_OK);
+    g_assert(-error < -AVAHI_ERR_MAX);
+    
+    reply = dbus_message_new_error(m, table[-error], text ? text : avahi_strerror(error));
     dbus_connection_send(c, reply, NULL);
     dbus_message_unref(reply);
     
@@ -467,7 +494,6 @@ fail:
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 }
 
-
 static void entry_group_callback(AvahiServer *s, AvahiEntryGroup *g, AvahiEntryGroupState state, gpointer userdata) {
     EntryGroupInfo *i = userdata;
     DBusMessage *m;
@@ -506,7 +532,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
     
     /* Access control */
     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
-        return respond_error(c, m, DBUS_ERROR_ACCESS_DENIED, NULL);
+        return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
     
     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
 
@@ -548,10 +574,10 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
             goto fail;
         }
 
-        b = avahi_entry_group_is_empty(i->entry_group);
-        
+        b = !!avahi_entry_group_is_empty(i->entry_group);
+
         reply = dbus_message_new_method_return(m);
-        dbus_message_append_args(m, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
+        dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
         dbus_connection_send(c, reply, NULL);
         dbus_message_unref(reply);
         
@@ -584,7 +610,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
                 DBUS_TYPE_STRING, &host,
                 DBUS_TYPE_UINT16, &port, 
                 DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &txt, &txt_len,
-                DBUS_TYPE_INVALID) || !type || !*type || !name || !*name || !port) {
+                DBUS_TYPE_INVALID) || !type || !name) {
             avahi_log_warn("Error parsing EntryGroup::AddService message");
             goto fail;
         }
@@ -592,7 +618,7 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
             avahi_log_warn("Too many entries per entry group, client request failed.");
             dbus_free_string_array(txt);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_ENTRIES, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
         }
 
         strlst = avahi_string_list_new_from_array((const gchar**) txt, txt_len);
@@ -605,9 +631,8 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
             host = NULL;
 
         if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
-            avahi_log_warn("Failed to add service: %s", name);
             avahi_string_list_free(strlst);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_INVALID_SERVICE, NULL);
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         } else
             i->n_entries ++;
         
@@ -626,25 +651,23 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
                 DBUS_TYPE_INT32, &protocol,
                 DBUS_TYPE_STRING, &name,
                 DBUS_TYPE_STRING, &address,
-                DBUS_TYPE_INVALID) || !name || !*name || !address || !*address) {
+                DBUS_TYPE_INVALID) || !name || !address) {
             avahi_log_warn("Error parsing EntryGroup::AddAddress message");
             goto fail;
         }
 
         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
             avahi_log_warn("Too many entries per entry group, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_ENTRIES, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
         }
         
         if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
-            avahi_log_warn("Error parsing address data");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_INVALID_ADDRESS, NULL);
+            return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
         }
 
-        if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0) {
-            avahi_log_warn("Failed to add service: %s", name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_INVALID_ADDRESS, NULL);
-        } else
+        if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
+        else
             i->n_entries ++;
         
         return respond_ok(c, m);
@@ -661,7 +684,6 @@ fail:
 
 static void host_name_resolver_callback(AvahiHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const gchar *host_name, const AvahiAddress *a, gpointer userdata) {
     HostNameResolverInfo *i = userdata;
-    DBusMessage *reply;
     
     g_assert(r);
     g_assert(host_name);
@@ -670,6 +692,7 @@ static void host_name_resolver_callback(AvahiHostNameResolver *r, AvahiIfIndex i
     if (event == AVAHI_RESOLVER_FOUND) {
         char t[256], *pt = t;
         gint32 i_interface, i_protocol, i_aprotocol;
+        DBusMessage *reply;
 
         g_assert(a);
         avahi_address_snprint(t, sizeof(t), a);
@@ -688,20 +711,19 @@ static void host_name_resolver_callback(AvahiHostNameResolver *r, AvahiIfIndex i
             DBUS_TYPE_STRING, &pt,
             DBUS_TYPE_INVALID);
 
+        dbus_connection_send(server->bus, reply, NULL);
+        dbus_message_unref(reply);
     } else {
         g_assert(event == AVAHI_RESOLVER_TIMEOUT);
-        reply = dbus_message_new_error(i->message, AVAHI_DBUS_ERROR_TIMEOUT, NULL);
-    }
 
-    dbus_connection_send(server->bus, reply, NULL);
-    dbus_message_unref(reply);
+        respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
+    }
 
     host_name_resolver_free(i);
 }
 
 static void address_resolver_callback(AvahiAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const gchar *host_name, gpointer userdata) {
     AddressResolverInfo *i = userdata;
-    DBusMessage *reply;
     
     g_assert(r);
     g_assert(address);
@@ -710,6 +732,7 @@ static void address_resolver_callback(AvahiAddressResolver *r, AvahiIfIndex inte
     if (event == AVAHI_RESOLVER_FOUND) {
         char t[256], *pt = t;
         gint32 i_interface, i_protocol, i_aprotocol;
+        DBusMessage *reply;
 
         g_assert(host_name);
         avahi_address_snprint(t, sizeof(t), address);
@@ -728,14 +751,13 @@ static void address_resolver_callback(AvahiAddressResolver *r, AvahiIfIndex inte
             DBUS_TYPE_STRING, &host_name,
             DBUS_TYPE_INVALID);
 
+        dbus_connection_send(server->bus, reply, NULL);
+        dbus_message_unref(reply);
     } else {
         g_assert(event == AVAHI_RESOLVER_TIMEOUT);
-        reply = dbus_message_new_error(i->message, AVAHI_DBUS_ERROR_TIMEOUT, NULL);
+        respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
     }
 
-    dbus_connection_send(server->bus, reply, NULL);
-    dbus_message_unref(reply);
-
     address_resolver_free(i);
 }
 
@@ -760,7 +782,7 @@ static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage
     
     /* Access control */
     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
-        return respond_error(c, m, DBUS_ERROR_ACCESS_DENIED, NULL);
+        return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
     
     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
 
@@ -828,7 +850,7 @@ static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMe
     
     /* Access control */
     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
-        return respond_error(c, m, DBUS_ERROR_ACCESS_DENIED, NULL);
+        return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
     
     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
 
@@ -894,11 +916,11 @@ static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage
 
     /* Introspection */
     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
-        return handle_introspect(c, m, "ServiceBrowser.introspect");
+        return handle_introspect(c, m, "ServiceBrowser.Introspect");
     
     /* Access control */
     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
-        return respond_error(c, m, DBUS_ERROR_ACCESS_DENIED, NULL);
+        return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
     
     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
 
@@ -964,7 +986,6 @@ static void service_resolver_callback(
     gpointer userdata) {
     
     ServiceResolverInfo *i = userdata;
-    DBusMessage *reply;
     
     g_assert(r);
     g_assert(i);
@@ -975,6 +996,7 @@ static void service_resolver_callback(
         gchar **array;
         guint n, j;
         AvahiStringList *p;
+        DBusMessage *reply;
 
         g_assert(host_name);
         
@@ -1009,18 +1031,17 @@ static void service_resolver_callback(
         for (j = 0; j < n; j++)
             g_free(array[j]);
 
+        dbus_connection_send(server->bus, reply, NULL);
+        dbus_message_unref(reply);
     } else {
         g_assert(event == AVAHI_RESOLVER_TIMEOUT);
-        reply = dbus_message_new_error(i->message, AVAHI_DBUS_ERROR_TIMEOUT, NULL);
-    }
 
-    dbus_connection_send(server->bus, reply, NULL);
-    dbus_message_unref(reply);
+        respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
+    }
 
     service_resolver_free(i);
 }
 
-
 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
     DBusError error;
 
@@ -1092,7 +1113,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
             gchar txt[256];
             g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
-            return respond_error(c, m, AVAHI_DBUS_ERROR_OS, txt);
+            return respond_error(c, m, AVAHI_ERR_OS, txt);
         }
 
         memset(&ifr, 0, sizeof(ifr));
@@ -1102,7 +1123,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             gchar txt[256];
             g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
             close(fd);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_OS, txt);
+            return respond_error(c, m, AVAHI_ERR_OS, txt);
         }
 
         close(fd);
@@ -1114,7 +1135,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         int fd;
         struct ifreq ifr;
         
-        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n || !*n) {
+        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
             avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
             goto fail;
         }
@@ -1122,7 +1143,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
             gchar txt[256];
             g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
-            return respond_error(c, m, AVAHI_DBUS_ERROR_OS, txt);
+            return respond_error(c, m, AVAHI_ERR_OS, txt);
         }
 
         memset(&ifr, 0, sizeof(ifr));
@@ -1132,7 +1153,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             gchar txt[256];
             g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
             close(fd);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_OS, txt);
+            return respond_error(c, m, AVAHI_ERR_OS, txt);
         }
 
         close(fd);
@@ -1142,7 +1163,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
         gchar *n, * t;
         
-        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n || !*n) {
+        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
             avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
             goto fail;
         }
@@ -1156,7 +1177,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
         gchar *n, *t;
         
-        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n || !*n) {
+        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
             avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
             goto fail;
         }
@@ -1186,12 +1207,12 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         i = g_new(EntryGroupInfo, 1);
@@ -1203,9 +1224,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         client->n_objects++;
         
         if (!(i->entry_group = avahi_entry_group_new(avahi_server, entry_group_callback, i))) {
-            avahi_log_warn("Failed to create entry group");
             entry_group_free(i);
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
 
         dbus_connection_register_object_path(c, i->path, &vtable, i);
@@ -1223,19 +1243,19 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
                 DBUS_TYPE_INT32, &protocol,
                 DBUS_TYPE_STRING, &name,
                 DBUS_TYPE_INT32, &aprotocol,
-                DBUS_TYPE_INVALID) || !name || !*name) {
+                DBUS_TYPE_INVALID) || !name) {
             avahi_log_warn("Error parsing Server::ResolveHostName message");
             goto fail;
         }
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         i = g_new(HostNameResolverInfo, 1);
@@ -1246,8 +1266,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
 
         if (!(i->host_name_resolver = avahi_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, host_name_resolver_callback, i))) {
             host_name_resolver_free(i);
-            avahi_log_warn("Failed to create host name resolver");
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
         return DBUS_HANDLER_RESULT_HANDLED;
@@ -1264,24 +1283,22 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
                 DBUS_TYPE_INT32, &interface,
                 DBUS_TYPE_INT32, &protocol,
                 DBUS_TYPE_STRING, &address,
-                DBUS_TYPE_INVALID) || !address || !*address) {
+                DBUS_TYPE_INVALID) || !address) {
             avahi_log_warn("Error parsing Server::ResolveAddress message");
             goto fail;
         }
 
-        if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)) {
-            avahi_log_warn("Error parsing address data");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_INVALID_ADDRESS, NULL);
-        }
+        if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
+            return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         i = g_new(AddressResolverInfo, 1);
@@ -1292,8 +1309,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
 
         if (!(i->address_resolver = avahi_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, address_resolver_callback, i))) {
             address_resolver_free(i);
-            avahi_log_warn("Failed to create address resolver");
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
         return DBUS_HANDLER_RESULT_HANDLED;
@@ -1326,12 +1342,12 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         if (!*domain)
@@ -1345,9 +1361,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         client->n_objects++;
 
         if (!(i->domain_browser = avahi_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, domain_browser_callback, i))) {
-            avahi_log_warn("Failed to create domain browser");
             domain_browser_free(i);
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
         dbus_connection_register_object_path(c, i->path, &vtable, i);
@@ -1379,13 +1394,13 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
 
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         if (!*domain)
@@ -1399,9 +1414,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         client->n_objects++;
 
         if (!(i->service_type_browser = avahi_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, service_type_browser_callback, i))) {
-            avahi_log_warn("Failed to create service type browser");
             service_type_browser_free(i);
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
         dbus_connection_register_object_path(c, i->path, &vtable, i);
@@ -1427,20 +1441,20 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
                 DBUS_TYPE_INT32, &protocol,
                 DBUS_TYPE_STRING, &type,
                 DBUS_TYPE_STRING, &domain,
-                DBUS_TYPE_INVALID) || !type || !*type) {
+                DBUS_TYPE_INVALID) || !type) {
             avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
             goto fail;
         }
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
 
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         if (!*domain)
@@ -1454,9 +1468,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         client->n_objects++;
 
         if (!(i->service_browser = avahi_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, service_browser_callback, i))) {
-            avahi_log_warn("Failed to create service browser");
             service_browser_free(i);
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
         dbus_connection_register_object_path(c, i->path, &vtable, i);
@@ -1476,19 +1489,19 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
                 DBUS_TYPE_STRING, &type,
                 DBUS_TYPE_STRING, &domain,
                 DBUS_TYPE_INT32, &aprotocol,
-                DBUS_TYPE_INVALID) || !name || !*name || !type || !*type) {
+                DBUS_TYPE_INVALID) || !name || !type) {
             avahi_log_warn("Error parsing Server::ResolveService message");
             goto fail;
         }
 
         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
             avahi_log_warn("Too many clients, client request failed.");
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_CLIENTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
         
         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
-            return respond_error(c, m, AVAHI_DBUS_ERROR_TOO_MANY_OBJECTS, NULL);
+            return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
         }
 
         if (!*domain)
@@ -1502,8 +1515,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
 
         if (!(i->service_resolver = avahi_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, service_resolver_callback, i))) {
             service_resolver_free(i);
-            avahi_log_warn("Failed to create service resolver");
-            goto fail;
+            return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
         return DBUS_HANDLER_RESULT_HANDLED;
index 1083416811bcb5625799852bb0f544e058461d0c..99bf86036d5fd45449d295f73a5ea96ce81c5914 100644 (file)
@@ -150,6 +150,7 @@ static AvahiEntryGroup* add_dns_servers(AvahiServer *s, AvahiEntryGroup* g, gcha
         else
             if (avahi_server_add_dns_server_address(s, g, -1, AF_UNSPEC, NULL, AVAHI_DNS_SERVER_RESOLVE, &a, 53) < 0) {
                 avahi_entry_group_free(g);
+                avahi_log_error("Failed to add DNS server address: %s", avahi_strerror(avahi_server_errno(s)));
                 return NULL;
             }
     }
@@ -500,6 +501,7 @@ static gint run_server(DaemonConfig *c) {
     gint r = -1;
     GIOChannel *io = NULL;
     guint watch_id = (guint) -1;
+    gint error;
 
     g_assert(c);
     
@@ -527,8 +529,10 @@ static gint run_server(DaemonConfig *c) {
             goto finish;
 #endif
     
-    if (!(avahi_server = avahi_server_new(NULL, &c->server_config, server_callback, c)))
+    if (!(avahi_server = avahi_server_new(NULL, &c->server_config, server_callback, c, &error))) {
+        avahi_log_error("Failed to create server: %s", avahi_strerror(error));
         goto finish;
+    }
 
     load_resolv_conf(c);
     
index 8c54eab6d11494bcef273736917ddd3f7dd509f3..0fdff1400209e8ed73baee47f45ffa4042eca0cc 100644 (file)
@@ -193,9 +193,6 @@ static void add_static_service_group_to_server(StaticServiceGroup *g) {
 
     g_assert(g);
     
-    if (g->entry_group)
-        return;
-    
     if (g->chosen_name)
         g_free(g->chosen_name);
     
@@ -218,7 +215,9 @@ static void add_static_service_group_to_server(StaticServiceGroup *g) {
                 g->chosen_name, s->type, 
                 s->domain_name, s->host_name, s->port,
                 s->txt_records) < 0) {
-            avahi_log_error("Failed to add service '%s' of type '%s', ignoring service group (%s)", g->chosen_name, s->type, g->filename);
+            avahi_log_error("Failed to add service '%s' of type '%s', ignoring service group (%s): %s",
+                            g->chosen_name, s->type, g->filename,
+                            avahi_strerror(avahi_server_errno(avahi_server)));
             remove_static_service_group_from_server(g);
             return;
         }
index daecdaa4908516fda806b302762fd685b5c9d55f..00984ec1111ed0727f98cd0f47aebf0977b48e05 100644 (file)
@@ -267,6 +267,7 @@ int main(int argc, char *argv[]) {
     GladeXML *xml;
     AvahiServerConfig config;
     GtkTreeViewColumn *c;
+    gint error;
 
     gtk_init(&argc, &argv);
     glade_init();
@@ -293,9 +294,11 @@ int main(int argc, char *argv[]) {
     
     avahi_server_config_init(&config);
     config.publish_hinfo = config.publish_addresses = config.publish_domain = config.publish_workstation = FALSE;
-    server = avahi_server_new(NULL, &config, NULL, NULL);
+    server = avahi_server_new(NULL, &config, NULL, NULL, &error);
     avahi_server_config_free(&config);
 
+    g_assert(server);
+
     service_type_browser = avahi_service_type_browser_new(server, -1, AF_UNSPEC, argc >= 2 ? argv[1] : NULL, service_type_browser_callback, NULL);
 
     gtk_main();
index 90b908c26eb569e04d81125894686364703562ff..144ee1288cca72bd76b66d4b2d9ab27bc966d08d 100644 (file)
@@ -24,14 +24,18 @@ pythonscripts = \
        avahi-publish-service \
        avahi-dump-all \
        avahi-discover \
-       avahi-bookmarks
+       avahi-bookmarks \
+       avahi-resolve-host-name \
+       avahi-resolve-address
 
 EXTRA_DIST = \
        avahi-publish-address.in \
        avahi-publish-service.in \
        avahi-dump-all.in \
        avahi-discover.in \
-       avahi-bookmarks.in
+       avahi-bookmarks.in \
+       avahi-resolve-host-name.in \
+       avahi-resolve-address.in
 
 if HAVE_PYTHON
 bin_SCRIPTS = $(pythonscripts)
@@ -58,4 +62,12 @@ avahi-bookmarks: avahi-bookmarks.in
        sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
        chmod +x $@
 
+avahi-resolve-host-name: avahi-resolve-host-name.in
+       sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
+       chmod +x $@
+
+avahi-resolve-address: avahi-resolve-address.in
+       sed -e 's,@PYTHON\@,$(PYTHON),g' $< > $@
+       chmod +x $@
+
 CLEANFILES = $(pythonscripts)
diff --git a/avahi-utils/avahi-resolve-address.in b/avahi-utils/avahi-resolve-address.in
new file mode 100755 (executable)
index 0000000..b72a95b
--- /dev/null
@@ -0,0 +1,53 @@
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import sys, getopt
+
+try:
+    import avahi, gobject, dbus
+except ImportError:
+    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
+    sys.exit(1)
+
+try:
+    import dbus.glib
+except ImportError, e:
+    pass
+
+
+if len(sys.argv) <= 1:
+    print "Please specify host name(s) to resolve."
+    sys.exit(1)
+
+bus = dbus.SystemBus()
+server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+
+ret = 0
+
+for a in sys.argv[1:]:
+    try:
+        r = server.ResolveAddress(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, a)
+        print r[3], r[4]
+    except dbus.DBusException, e:
+        print "Resolving '%s' failed: %s" % (a, str(e))
+        ret = 1
+
+sys.exit(ret)
diff --git a/avahi-utils/avahi-resolve-host-name.in b/avahi-utils/avahi-resolve-host-name.in
new file mode 100755 (executable)
index 0000000..cc24526
--- /dev/null
@@ -0,0 +1,53 @@
+#!@PYTHON@
+# -*-python-*-
+# $Id$
+
+# This file is part of avahi.
+#
+# avahi is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# avahi is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+# License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with avahi; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA.
+
+import sys, getopt
+
+try:
+    import avahi, gobject, dbus
+except ImportError:
+    print "Sorry, to use this tool you need to install Avahi, pygtk and python-dbus."
+    sys.exit(1)
+
+try:
+    import dbus.glib
+except ImportError, e:
+    pass
+
+
+if len(sys.argv) <= 1:
+    print "Please specify host name(s) to resolve."
+    sys.exit(1)
+
+bus = dbus.SystemBus()
+server = dbus.Interface(bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
+
+ret = 0
+
+for name in sys.argv[1:]:
+    try:
+        r = server.ResolveHostName(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, name, avahi.PROTO_UNSPEC)
+        print r[2], r[4]
+    except dbus.DBusException, e:
+        print "Resolving '%s' failed: %s" % (name, str(e))
+        ret = 1
+
+sys.exit(ret)
index f081d415152f36bb12ee7064238464356c6694fe..315fbd1eb76b95720a2d7d929cc04fe2274e4814 100644 (file)
@@ -173,7 +173,7 @@ EXPAND_ONLY_PREDEF     = NO
 SEARCH_INCLUDES        = YES
 INCLUDE_PATH           = 
 INCLUDE_FILE_PATTERNS  = 
-PREDEFINED             = 
+PREDEFINED             = DOXYGEN_SHOULD_SKIP_THIS
 EXPAND_AS_DEFINED      = 
 SKIP_FUNCTION_MACROS   = YES
 #---------------------------------------------------------------------------
index bb8eed82f761b52cd7f0555c5c08d588b7d9e250..c58d230299464c7b8f2d6d8073218f7af30c9702 100644 (file)
@@ -77,6 +77,8 @@ int main(int argc, char*argv[]) {
     AvahiServerConfig config;
     AvahiServer *server = NULL;
     AvahiServiceBrowser *sb;
+    gint error;
+    int ret = 1;
 
     /* Do not publish any local records */
     avahi_server_config_init(&config);
@@ -86,11 +88,17 @@ int main(int argc, char*argv[]) {
     config.publish_domain = FALSE;
     
     /* Allocate a new server */
-    server = avahi_server_new(NULL, &config, NULL, NULL);
+    server = avahi_server_new(NULL, &config, NULL, NULL, &error);
 
     /* Free the configuration data */
     avahi_server_config_free(&config);
 
+    /* Check wether creating the server object succeeded */
+    if (!server) {
+        g_message("Failed to create server: %s", avahi_strerror(error));
+        goto fail;
+    }
+    
     /* Create the service browser */
     sb = avahi_service_browser_new(server, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_http._tcp", NULL, browse_callback, server);
     
@@ -98,6 +106,10 @@ int main(int argc, char*argv[]) {
     main_loop = g_main_loop_new(NULL, FALSE);
     g_main_loop_run(main_loop);
 
+    ret = 0;
+    
+fail:
+    
     /* Cleanup things */
     if (sb)
         avahi_service_browser_free(sb);
@@ -108,5 +120,5 @@ int main(int argc, char*argv[]) {
     if (main_loop)
         g_main_loop_unref(main_loop);
 
-    return 0;
+    return ret;
 }
index 7c9879ccf66a49d6df79b20d28e8d646e1e2460c..a936147a39e9f0c8276f14ebd53073789ce25721 100644 (file)
@@ -121,7 +121,9 @@ static void server_callback(AvahiServer *s, AvahiServerState state, gpointer use
 int main(int argc, char*argv[]) {
     AvahiServerConfig config;
     AvahiServer *server = NULL;
-
+    gint error;
+    int ret = 1;
+    
     srand(time(NULL));
     
     name = g_strdup("MegaPrinter");
@@ -132,15 +134,25 @@ int main(int argc, char*argv[]) {
     config.publish_workstation = FALSE;
     
     /* Allocate a new server */
-    server = avahi_server_new(NULL, &config, server_callback, NULL);
+    server = avahi_server_new(NULL, &config, server_callback, NULL, &error);
 
     /* Free the configuration data */
     avahi_server_config_free(&config);
+
+    /* Check wether creating the server object succeeded */
+    if (!server) {
+        g_message("Failed to create server: %s", avahi_strerror(error));
+        goto fail;
+    }
     
     /* Run the main loop */
     main_loop = g_main_loop_new(NULL, FALSE);
     g_main_loop_run(main_loop);
 
+    ret = 0;
+    
+fail:
+    
     /* Cleanup things */
     if (group)
         avahi_entry_group_free(group);
@@ -153,5 +165,5 @@ int main(int argc, char*argv[]) {
 
     g_free(name);
     
-    return 0;
+    return ret;
 }