summaryrefslogtreecommitdiffstats
path: root/avahi-core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2005-08-05 18:59:21 +0000
committerLennart Poettering <lennart@poettering.net>2005-08-05 18:59:21 +0000
commit0632e854728e8e64552ae08f90852d4a2658539e (patch)
tree0fab7d52e01da7ab9b81b8409dcf70cceb7d2852 /avahi-core
parentd76069e946b4e89c828c96340677e40f583080c9 (diff)
* add proper error codes and patch everything to make use of it
* 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
Diffstat (limited to 'avahi-core')
-rw-r--r--avahi-core/avahi-reflector.c3
-rw-r--r--avahi-core/avahi-test.c3
-rw-r--r--avahi-core/browse-dns-server.c16
-rw-r--r--avahi-core/browse-domain.c17
-rw-r--r--avahi-core/browse-service-type.c13
-rw-r--r--avahi-core/browse-service.c21
-rw-r--r--avahi-core/browse.c10
-rw-r--r--avahi-core/conformance-test.c3
-rw-r--r--avahi-core/core.h42
-rw-r--r--avahi-core/resolve-address.c5
-rw-r--r--avahi-core/resolve-host-name.c21
-rw-r--r--avahi-core/resolve-service.c27
-rw-r--r--avahi-core/server.c190
-rw-r--r--avahi-core/server.h4
14 files changed, 329 insertions, 46 deletions
diff --git a/avahi-core/avahi-reflector.c b/avahi-core/avahi-reflector.c
index 7af0dd4..0a91b87 100644
--- a/avahi-core/avahi-reflector.c
+++ b/avahi-core/avahi-reflector.c
@@ -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);
diff --git a/avahi-core/avahi-test.c b/avahi-core/avahi-test.c
index cc950d4..5db2473 100644
--- a/avahi-core/avahi-test.c
+++ b/avahi-core/avahi-test.c
@@ -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);
diff --git a/avahi-core/browse-dns-server.c b/avahi-core/browse-dns-server.c
index f8e8f30..057f3e3 100644
--- a/avahi-core/browse-dns-server.c
+++ b/avahi-core/browse-dns-server.c
@@ -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);
}
diff --git a/avahi-core/browse-domain.c b/avahi-core/browse-domain.c
index c6331b4..de3cb1b 100644
--- a/avahi-core/browse-domain.c
+++ b/avahi-core/browse-domain.c
@@ -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);
}
diff --git a/avahi-core/browse-service-type.c b/avahi-core/browse-service-type.c
index 7cd6cf7..3534b6f 100644
--- a/avahi-core/browse-service-type.c
+++ b/avahi-core/browse-service-type.c
@@ -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);
}
diff --git a/avahi-core/browse-service.c b/avahi-core/browse-service.c
index f72ce6c..34a2536 100644
--- a/avahi-core/browse-service.c
+++ b/avahi-core/browse-service.c
@@ -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);
diff --git a/avahi-core/browse.c b/avahi-core/browse.c
index 5f4d216..5885cb4 100644
--- a/avahi-core/browse.c
+++ b/avahi-core/browse.c
@@ -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;
diff --git a/avahi-core/conformance-test.c b/avahi-core/conformance-test.c
index ccc9a12..13704c3 100644
--- a/avahi-core/conformance-test.c
+++ b/avahi-core/conformance-test.c
@@ -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);
diff --git a/avahi-core/core.h b/avahi-core/core.h
index 25e9c0a..1adf244 100644
--- a/avahi-core/core.h
+++ b/avahi-core/core.h
@@ -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
diff --git a/avahi-core/resolve-address.c b/avahi-core/resolve-address.c
index d315ac9..89f9bcf 100644
--- a/avahi-core/resolve-address.c
+++ b/avahi-core/resolve-address.c
@@ -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;
}
diff --git a/avahi-core/resolve-host-name.c b/avahi-core/resolve-host-name.c
index 0ab2e73..c18722d 100644
--- a/avahi-core/resolve-host-name.c
+++ b/avahi-core/resolve-host-name.c
@@ -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) {
diff --git a/avahi-core/resolve-service.c b/avahi-core/resolve-service.c
index b15af4f..2ad38f8 100644
--- a/avahi-core/resolve-service.c
+++ b/avahi-core/resolve-service.c
@@ -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;
}
diff --git a/avahi-core/server.c b/avahi-core/server.c
index 3c38507..c4acf35 100644
--- a/avahi-core/server.c
+++ b/avahi-core/server.c
@@ -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;
+}
+
diff --git a/avahi-core/server.h b/avahi-core/server.h
index 7049f58..6572fbb 100644
--- a/avahi-core/server.h
+++ b/avahi-core/server.h
@@ -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