#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
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;
+}
guint32 ttl; /**< DNS TTL of this record */
union {
-
struct {
gpointer data;
guint16 size;
} generic; /**< Generic record data for unknown types */
-
struct {
guint16 priority;
/** 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
*(--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;
+}
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
AvahiServer *server;
AvahiServerConfig config;
GMainLoop *loop;
+ gint error;
avahi_server_config_init(&config);
config.publish_hinfo = FALSE;
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);
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);
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);
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;
}
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);
}
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;
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);
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;
}
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);
}
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);
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;
}
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);
}
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;
}
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);
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;
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);
#include <avahi-common/cdecl.h>
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
AVAHI_C_DECL_BEGIN
+#endif
/** An mDNS responder object */
typedef struct AvahiServer AvahiServer;
/** 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 */
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);
/** 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
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;
}
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);
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) {
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);
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;
}
}
}
+
if (!ours) {
if (won)
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);
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);
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,
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;
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;
}
s->hinfo_entry_group = NULL;
s->browse_domain_entry_group = NULL;
register_stuff(s);
+
+ s->error = AVAHI_OK;
return s;
}
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;
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);
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;
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;
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);
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));
}
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)
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;
}
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));
}
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);
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(
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);
if (g->state == state)
return;
+ g_assert(state >= AVAHI_ENTRY_GROUP_UNCOMMITED && state <= AVAHI_ENTRY_GROUP_COLLISION);
+
g->state = state;
if (g->callback)
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++;
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;
+}
+
/* 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);
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
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);
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;
/* 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")) {
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);
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;
}
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);
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 ++;
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);
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);
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);
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);
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);
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);
}
/* 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")) {
/* 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")) {
/* 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")) {
gpointer userdata) {
ServiceResolverInfo *i = userdata;
- DBusMessage *reply;
g_assert(r);
g_assert(i);
gchar **array;
guint n, j;
AvahiStringList *p;
+ DBusMessage *reply;
g_assert(host_name);
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;
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));
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);
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;
}
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));
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);
} 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;
}
} 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;
}
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);
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);
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);
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;
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);
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;
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)
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);
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)
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);
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)
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);
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)
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;
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;
}
}
gint r = -1;
GIOChannel *io = NULL;
guint watch_id = (guint) -1;
+ gint error;
g_assert(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);
g_assert(g);
- if (g->entry_group)
- return;
-
if (g->chosen_name)
g_free(g->chosen_name);
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;
}
GladeXML *xml;
AvahiServerConfig config;
GtkTreeViewColumn *c;
+ gint error;
gtk_init(&argc, &argv);
glade_init();
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();
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)
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)
--- /dev/null
+#!@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)
--- /dev/null
+#!@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)
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
-PREDEFINED =
+PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
AvahiServerConfig config;
AvahiServer *server = NULL;
AvahiServiceBrowser *sb;
+ gint error;
+ int ret = 1;
/* Do not publish any local records */
avahi_server_config_init(&config);
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);
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);
if (main_loop)
g_main_loop_unref(main_loop);
- return 0;
+ return ret;
}
int main(int argc, char*argv[]) {
AvahiServerConfig config;
AvahiServer *server = NULL;
-
+ gint error;
+ int ret = 1;
+
srand(time(NULL));
name = g_strdup("MegaPrinter");
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);
g_free(name);
- return 0;
+ return ret;
}