#include <avahi-common/address.h>
#include <avahi-common/defs.h>
#include <avahi-common/watch.h>
+#include <avahi-common/timeval.h>
#include <avahi-core/rr.h>
AVAHI_C_DECL_BEGIN
int publish_a_on_ipv6; /**< Publish an IPv4 A RR on IPv6 sockets */
int publish_aaaa_on_ipv4; /**< Publish an IPv4 A RR on IPv6 sockets */
unsigned n_cache_entries_max; /**< Maximum number of cache entries per interface */
+ AvahiUsec ratelimit_interval; /**< If non-zero, rate-limiting interval parameter. */
+ unsigned ratelimit_burst; /**< If ratelimit_interval is non-zero, rate-limiting burst parameter. */
} AvahiServerConfig;
/** Allocate a new mDNS responder object. */
hw->index = idx;
hw->mac_address_size = 0;
hw->entry_group = NULL;
+ hw->ratelimit_begin.tv_sec = 0;
+ hw->ratelimit_begin.tv_usec = 0;
+ hw->ratelimit_counter = 0;
AVAHI_LLIST_HEAD_INIT(AvahiInterface, hw->interfaces);
AVAHI_LLIST_PREPEND(AvahiHwInterface, hardware, m->hw_interfaces, hw);
assert(!a || a->proto == i->protocol);
+ if (i->monitor->server->config.ratelimit_interval > 0) {
+ struct timeval now, end;
+
+ gettimeofday(&now, NULL);
+
+ end = i->hardware->ratelimit_begin;
+ avahi_timeval_add(&end, i->monitor->server->config.ratelimit_interval);
+
+ if (i->hardware->ratelimit_begin.tv_sec <= 0 ||
+ avahi_timeval_compare(&end, &now) < 0) {
+
+ i->hardware->ratelimit_begin = now;
+ i->hardware->ratelimit_counter = 0;
+ }
+
+ if (i->hardware->ratelimit_counter > i->monitor->server->config.ratelimit_burst)
+ return;
+
+ i->hardware->ratelimit_counter++;
+ }
+
if (i->protocol == AVAHI_PROTO_INET && i->monitor->server->fd_ipv4 >= 0)
avahi_send_dns_packet_ipv4(i->monitor->server->fd_ipv4, i->hardware->index, p, i->mcast_joined ? &i->local_mcast_address.data.ipv4 : NULL, a ? &a->data.ipv4 : NULL, port);
else if (i->protocol == AVAHI_PROTO_INET6 && i->monitor->server->fd_ipv6 >= 0)
AvahiSEntryGroup *entry_group;
+ /* Packet rate limiting */
+ struct timeval ratelimit_begin;
+ unsigned ratelimit_counter;
+
AVAHI_LLIST_HEAD(AvahiInterface, interfaces);
};
#include <avahi-common/llist.h>
#include <avahi-common/watch.h>
+#include <avahi-common/timeval.h>
#include "core.h"
#include "iface.h"
c->publish_aaaa_on_ipv4 = 1;
c->publish_a_on_ipv6 = 0;
c->n_cache_entries_max = AVAHI_DEFAULT_CACHE_ENTRIES_MAX;
+ c->ratelimit_interval = 0;
+ c->ratelimit_burst = 0;
return c;
}
#clients-max=4096
#objects-per-client-max=1024
#entries-per-entry-group-max=32
+ratelimit-interval-usec=1000000
+ratelimit-burst=1000
[wide-area]
enable-wide-area=yes
return 0;
}
+static int parse_usec(const char *s, AvahiUsec *u) {
+ char *e = NULL;
+ unsigned long long ull;
+ AvahiUsec k;
+
+ errno = 0;
+ ull = strtoull(s, &e, 0);
+
+ if (!e || *e || errno != 0)
+ return -1;
+
+ k = (AvahiUsec) ull;
+
+ if ((unsigned long long) k != ull)
+ return -1;
+
+ *u = k;
+ return 0;
+}
+
static int load_config_file(DaemonConfig *c) {
int r = -1;
AvahiIniFile *f;
c->server_config.deny_interfaces = avahi_string_list_add(c->server_config.deny_interfaces, *t);
avahi_strfreev(e);
+ } else if (strcasecmp(p->key, "ratelimit-interval-usec") == 0) {
+ AvahiUsec k;
+
+ if (parse_usec(p->value, &k) < 0) {
+ avahi_log_error("Invalid ratelimit-interval-usec setting %s", p->value);
+ goto finish;
+ }
+
+ c->server_config.ratelimit_interval = k;
+
+ } else if (strcasecmp(p->key, "ratelimit-burst") == 0) {
+ unsigned k;
+
+ if (parse_unsigned(p->value, &k) < 0) {
+ avahi_log_error("Invalid ratelimit-burst setting %s", p->value);
+ goto finish;
+ }
+
+ c->server_config.ratelimit_burst = k;
+
} else if (strcasecmp(p->key, "cache-entries-max") == 0) {
unsigned k;
<option>
<p><opt>objects-per-client-max=</opt> Takes an unsigned
integer. The maximum number of objects (entry groups, browsers,
- resolvers) that may be registered per client at a time. If the
+ resolvers) that may be registered per D-Bus client at a time. If the
maximum number is reached further object creation will be
refused until at least one object is freed.</p>
</option>
<option>
<p><opt>entries-per-entry-group-max=</opt> Takes an unsigned
integer. The maximum number of entries (resource records) per
- entry group at a time. If the maximum number is reached further
- resource records may not be added to an entry group.</p>
+ entry group registered by a D-Bus client at a time. If the
+ maximum number is reached further resource records may not be
+ added to an entry group.</p>
</option>
+ <option>
+ <p><opt>ratelimit-interval-usec=</opt> Takes an unsigned
+ integer. Sets the per-interface packet rate-limiting interval
+ parameter. Together with <opt>ratelimit-burst=</opt> this may be
+ used to control the maximum number of packets Avahi will
+ generated in a specific period of time on an interface.</p>
+ </option>
+
+ <option>
+ <p><opt>ratelimit-burst=</opt> Takes an unsigned
+ integer. Sets the per-interface packet rate-limiting burst
+ parameter. Together with <opt>ratelimit-interval-usec=</opt> this may be
+ used to control the maximum number of packets Avahi will
+ generated in a specific period of time on an interface.</p>
+ </option>
</section>
<section name="Section [wide-area]">