From d7b03753f10d93d278091d39b95adf3b18a2770c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 29 Jun 2010 02:24:02 +0200 Subject: core: implement packet rate limiting and enable it by default --- avahi-core/core.h | 3 +++ avahi-core/iface.c | 24 ++++++++++++++++++++++++ avahi-core/iface.h | 4 ++++ avahi-core/internal.h | 1 + avahi-core/server.c | 2 ++ avahi-daemon/avahi-daemon.conf | 2 ++ avahi-daemon/main.c | 40 ++++++++++++++++++++++++++++++++++++++++ man/avahi-daemon.conf.5.xml.in | 22 +++++++++++++++++++--- 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 #include #include +#include #include 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 #include +#include #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 @@ @@ -167,10 +167,26 @@ + + +
-- cgit