]> git.meshlink.io Git - catta/commitdiff
core: implement packet rate limiting and enable it by default
authorLennart Poettering <lennart@poettering.net>
Tue, 29 Jun 2010 00:24:02 +0000 (02:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 29 Jun 2010 00:24:02 +0000 (02:24 +0200)
avahi-core/core.h
avahi-core/iface.c
avahi-core/iface.h
avahi-core/internal.h
avahi-core/server.c
avahi-daemon/avahi-daemon.conf
avahi-daemon/main.c
man/avahi-daemon.conf.5.xml.in

index 1f5012691affa92a397dd8f829899ca7ad6a1de1..f50c6128ad69ee6c35cc73497d8bd5794006d0a6 100644 (file)
@@ -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. */
index ad83fe465680da0f4823ef71740595fe990ef8b5..39a860ae7cc9eff13ec8bd3678d9e57904afcb90 100644 (file)
@@ -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)
index b38578c5761e2c45482530f8075472d92381e4c2..c3f24af05a7505e4374a98111ae2642d5ab26193 100644 (file)
@@ -85,6 +85,10 @@ struct AvahiHwInterface {
 
     AvahiSEntryGroup *entry_group;
 
+    /* Packet rate limiting */
+    struct timeval ratelimit_begin;
+    unsigned ratelimit_counter;
+
     AVAHI_LLIST_HEAD(AvahiInterface, interfaces);
 };
 
index eb7f14637bd0bc6847b7b47c45b89e55dca15b53..b8f930269c5b2fdf9679eacd2c12b065602e1fcf 100644 (file)
@@ -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"
index d7fd71bc31714dba42825cd285c3d84d6a69a34d..2b8f95fd56a50a234b5d891eba585391559279ce 100644 (file)
@@ -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;
 }
index 898cee959a8b028ed5103a06f037540fa9ca6946..c9928425f5c129aad75e3a1f42908a10e69bf0e7 100644 (file)
@@ -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
index ca1a85499ea9cfe593d3177ef19fbcd50249563f..8bd856eee68a84a8bb5175e2fd7354eb39e357bb 100644 (file)
@@ -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;
 
index 62f3a9dde6f653552b08748027a5d88990d57d5c..487645bbe6e83180b4a52f9cbf428a7b91a01a82 100644 (file)
     <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]">