summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2010-06-29 02:24:02 +0200
committerLennart Poettering <lennart@poettering.net>2010-06-29 02:24:02 +0200
commitd7b03753f10d93d278091d39b95adf3b18a2770c (patch)
tree49e7a335eac64aa01a84c3c1cd0003e83f02c8eb
parent17cb9485bbf194aadf94642eafe261303fe8a867 (diff)
core: implement packet rate limiting and enable it by default
-rw-r--r--avahi-core/core.h3
-rw-r--r--avahi-core/iface.c24
-rw-r--r--avahi-core/iface.h4
-rw-r--r--avahi-core/internal.h1
-rw-r--r--avahi-core/server.c2
-rw-r--r--avahi-daemon/avahi-daemon.conf2
-rw-r--r--avahi-daemon/main.c40
-rw-r--r--man/avahi-daemon.conf.5.xml.in22
8 files changed, 95 insertions, 3 deletions
diff --git a/avahi-core/core.h b/avahi-core/core.h
index 1f50126..f50c612 100644
--- a/avahi-core/core.h
+++ b/avahi-core/core.h
@@ -29,6 +29,7 @@ typedef struct AvahiServer AvahiServer;
#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
@@ -66,6 +67,8 @@ typedef struct AvahiServerConfig {
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. */
diff --git a/avahi-core/iface.c b/avahi-core/iface.c
index ad83fe4..39a860a 100644
--- a/avahi-core/iface.c
+++ b/avahi-core/iface.c
@@ -390,6 +390,9 @@ AvahiHwInterface *avahi_hw_interface_new(AvahiInterfaceMonitor *m, AvahiIfIndex
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);
@@ -571,6 +574,27 @@ void avahi_interface_send_packet_unicast(AvahiInterface *i, AvahiDnsPacket *p, c
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)
diff --git a/avahi-core/iface.h b/avahi-core/iface.h
index b38578c..c3f24af 100644
--- a/avahi-core/iface.h
+++ b/avahi-core/iface.h
@@ -85,6 +85,10 @@ struct AvahiHwInterface {
AvahiSEntryGroup *entry_group;
+ /* Packet rate limiting */
+ struct timeval ratelimit_begin;
+ unsigned ratelimit_counter;
+
AVAHI_LLIST_HEAD(AvahiInterface, interfaces);
};
diff --git a/avahi-core/internal.h b/avahi-core/internal.h
index eb7f146..b8f9302 100644
--- a/avahi-core/internal.h
+++ b/avahi-core/internal.h
@@ -25,6 +25,7 @@ typedef struct AvahiEntry AvahiEntry;
#include <avahi-common/llist.h>
#include <avahi-common/watch.h>
+#include <avahi-common/timeval.h>
#include "core.h"
#include "iface.h"
diff --git a/avahi-core/server.c b/avahi-core/server.c
index d7fd71b..2b8f95f 100644
--- a/avahi-core/server.c
+++ b/avahi-core/server.c
@@ -1591,6 +1591,8 @@ AvahiServerConfig* avahi_server_config_init(AvahiServerConfig *c) {
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;
}
diff --git a/avahi-daemon/avahi-daemon.conf b/avahi-daemon/avahi-daemon.conf
index 898cee9..c992842 100644
--- a/avahi-daemon/avahi-daemon.conf
+++ b/avahi-daemon/avahi-daemon.conf
@@ -35,6 +35,8 @@ use-ipv6=no
#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
diff --git a/avahi-daemon/main.c b/avahi-daemon/main.c
index ca1a854..8bd856e 100644
--- a/avahi-daemon/main.c
+++ b/avahi-daemon/main.c
@@ -551,6 +551,26 @@ static int parse_unsigned(const char *s, unsigned *u) {
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;
@@ -642,6 +662,26 @@ static int load_config_file(DaemonConfig *c) {
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;
diff --git a/man/avahi-daemon.conf.5.xml.in b/man/avahi-daemon.conf.5.xml.in
index 62f3a9d..487645b 100644
--- a/man/avahi-daemon.conf.5.xml.in
+++ b/man/avahi-daemon.conf.5.xml.in
@@ -159,7 +159,7 @@
<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>
@@ -167,10 +167,26 @@
<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]">