#include <string.h>
#include <sys/ioctl.h>
+#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <errno.h>
#include <avahi-common/dbus-watch-glue.h>
#include <avahi-common/alternative.h>
#include <avahi-common/error.h>
+#include <avahi-common/domain.h>
#include <avahi-core/log.h>
#include <avahi-core/core.h>
typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
-#define MAX_CLIENTS 20
-#define MAX_OBJECTS_PER_CLIENT 50
-#define MAX_ENTRIES_PER_ENTRY_GROUP 20
+#define CLIENTS_MAX 256
+#define OBJECTS_PER_CLIENT_MAX 50
+#define ENTRIES_PER_ENTRY_GROUP_MAX 20
/* #define VALGRIND_WORKAROUND 1 */
if (!create)
return NULL;
- if (server->n_clients >= MAX_CLIENTS)
+ if (server->n_clients >= CLIENTS_MAX)
return NULL;
/* If not existant yet, create a new entry */
}
-static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
+static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
DBusError error;
dbus_error_init(&error);
EntryGroupInfo *i = userdata;
DBusMessage *m;
int32_t t;
+ const char *e;
assert(s);
assert(g);
assert(i);
m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
+
t = (int32_t) state;
- dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
+ if (state == AVAHI_ENTRY_GROUP_FAILURE)
+ e = avahi_error_number_to_dbus(avahi_server_errno(s));
+ else if (state == AVAHI_ENTRY_GROUP_COLLISION)
+ e = AVAHI_DBUS_ERR_COLLISION;
+ else
+ e = AVAHI_DBUS_ERR_OK;
+
+ dbus_message_append_args(
+ m,
+ DBUS_TYPE_INT32, &t,
+ DBUS_TYPE_STRING, &e,
+ DBUS_TYPE_INVALID);
dbus_message_set_destination(m, i->client->name);
dbus_connection_send(server->bus, m, NULL);
dbus_message_unref(m);
}
+static int read_rdata(DBusMessage *m, int idx, void **rdata, uint32_t *size) {
+ DBusMessageIter iter, sub;
+ int n, j;
+ uint8_t *k;
+
+ assert(m);
+
+ dbus_message_iter_init(m, &iter);
+
+ for (j = 0; j < idx; j++)
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+ dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
+ goto fail;
+
+ dbus_message_iter_recurse(&iter, &sub);
+ dbus_message_iter_get_fixed_array(&sub, &k, &n);
+
+ *rdata = k;
+ *size = n;
+
+ return 0;
+
+fail:
+ avahi_log_warn("Error parsing data");
+
+ *rdata = NULL;
+ size = 0;
+ return -1;
+}
+
static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
DBusMessageIter iter, sub;
int j;
goto fail;
}
- if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
+ if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) {
avahi_string_list_free(strlst);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
}
goto fail;
}
- if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
+ if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
if (domain && !*domain)
goto fail;
}
- if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
+ if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
if (!(flags & AVAHI_PUBLISH_UPDATE))
i->n_entries ++;
+ return respond_ok(c, m);
+ } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord")) {
+ int32_t interface, protocol;
+ uint32_t flags, ttl, size;
+ uint16_t clazz, type;
+ char *name;
+ void *rdata;
+ AvahiRecord *r;
+
+ if (!dbus_message_get_args(
+ m, &error,
+ DBUS_TYPE_INT32, &interface,
+ DBUS_TYPE_INT32, &protocol,
+ DBUS_TYPE_UINT32, &flags,
+ DBUS_TYPE_STRING, &name,
+ DBUS_TYPE_UINT16, &clazz,
+ DBUS_TYPE_UINT16, &type,
+ DBUS_TYPE_UINT32, &ttl,
+ DBUS_TYPE_INVALID) || !name ||
+ read_rdata (m, 7, &rdata, &size)) {
+ avahi_log_warn("Error parsing EntryGroup::AddRecord message");
+ goto fail;
+ }
+
+ if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
+ return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
+
+ if (!avahi_is_valid_domain_name (name))
+ return respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL);
+
+ if (!(r = avahi_record_new_full (name, clazz, type, ttl)))
+ return respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL);
+
+ if (avahi_rdata_parse (r, rdata, size) < 0) {
+ avahi_record_unref (r);
+ return respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL);
+ }
+
+ if (avahi_server_add(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, r) < 0) {
+ avahi_record_unref (r);
+ return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
+ }
+
+ if (!(flags & AVAHI_PUBLISH_UPDATE))
+ i->n_entries ++;
+
+ avahi_record_unref (r);
+
return respond_ok(c, m);
}
+
avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
-static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
+static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
DBusError error;
dbus_error_init(&error);
} else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
int32_t idx;
int fd;
- struct ifreq ifr;
+ char name[IF_NAMESIZE];
+
if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
return respond_error(c, m, AVAHI_ERR_OS, txt);
}
- memset(&ifr, 0, sizeof(ifr));
-
- ifr.ifr_ifindex = idx;
-
- if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
+ if ((!if_indextoname(idx, name))) {
char txt[256];
snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
close(fd);
close(fd);
- return respond_string(c, m, ifr.ifr_name);
+ return respond_string(c, m, name);
#endif
} else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
char *n;
int fd;
- struct ifreq ifr;
+ int32_t idx;
if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
return respond_error(c, m, AVAHI_ERR_OS, txt);
}
- memset(&ifr, 0, sizeof(ifr));
- snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
-
- if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
+ if (!(idx = if_nametoindex(n))) {
char txt[256];
snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
close(fd);
close(fd);
- return respond_int32(c, m, ifr.ifr_ifindex);
+ return respond_int32(c, m, idx);
#endif
} else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
}
- if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
+ if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
}
void dbus_protocol_server_state_changed(AvahiServerState state) {
DBusMessage *m;
int32_t t;
+ const char *e;
if (!server)
return;
m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
t = (int32_t) state;
- dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
+
+ if (state == AVAHI_SERVER_COLLISION)
+ e = AVAHI_DBUS_ERR_COLLISION;
+ else if (state == AVAHI_SERVER_FAILURE)
+ e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
+ else
+ e = AVAHI_DBUS_ERR_OK;
+
+ dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID);
dbus_connection_send(server->bus, m, NULL);
dbus_message_unref(m);
}