]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Rate limit some triggers.
authorAlan T. DeKok <aland@freeradius.org>
Sun, 29 Apr 2012 16:59:25 +0000 (18:59 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Sun, 29 Apr 2012 16:59:25 +0000 (18:59 +0200)
e.g. LDAP query timeout

12 files changed:
src/include/radiusd.h
src/main/command.c
src/main/connection.c
src/main/exec.c
src/main/listen.c
src/main/process.c
src/main/radiusd.c
src/main/realms.c
src/main/threads.c
src/main/xlat.c
src/modules/rlm_ldap/rlm_ldap.c
src/modules/rlm_sql/sql.c

index bf2b0898f4a99648c827941750b01c6afa21f1d9..69f9bd6c8fccb35f854400692c99c61c51d5fff7 100644 (file)
@@ -682,7 +682,7 @@ int         radius_exec_program(const char *,  REQUEST *, int,
                                    VALUE_PAIR *input_pairs,
                                    VALUE_PAIR **output_pairs,
                                        int shell_escape);
-void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name);
+void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name, int quench);
 
 /* timestr.c */
 int            timestr_match(char *, time_t);
index e45fe20fa57c8ff66bd4c3c75411e030fcac3d1d..34c7b03b3f9ce22696a6433ef4c7780b53c14810 100644 (file)
@@ -326,7 +326,7 @@ static int command_hup(rad_listen_t *listener, int argc, char *argv[])
 
        snprintf(buffer, sizeof(buffer), "modules.%s.hup",
                 cf_section_name1(mi->cs));
-       exec_trigger(NULL, mi->cs, buffer);
+       exec_trigger(NULL, mi->cs, buffer, TRUE);
 
        return 1;               /* success */
 }
index d28343fc2e1bf4e9b685fbc5d4cd86249b31716f..01382b562f29a30d9a6745b131c4316c571f9d45 100644 (file)
@@ -221,7 +221,7 @@ static fr_connection_t *fr_connection_spawn(fr_connection_pool_t *fc,
 
        pthread_mutex_unlock(&fc->mutex);
 
-       if (fc->trigger) exec_trigger(NULL, fc->cs, "open");
+       if (fc->trigger) exec_trigger(NULL, fc->cs, "open", TRUE);
 
        return this;
 }
@@ -264,7 +264,7 @@ int fr_connection_add(fr_connection_pool_t *fc, void *conn)
 
        pthread_mutex_unlock(&fc->mutex);
 
-       if (fc->trigger) exec_trigger(NULL, fc->cs, "open");
+       if (fc->trigger) exec_trigger(NULL, fc->cs, "open", TRUE);
 
        return 1;
 }
@@ -273,7 +273,7 @@ int fr_connection_add(fr_connection_pool_t *fc, void *conn)
 static void fr_connection_close(fr_connection_pool_t *fc,
                                fr_connection_t *this)
 {
-       if (fc->trigger) exec_trigger(NULL, fc->cs, "close");
+       if (fc->trigger) exec_trigger(NULL, fc->cs, "close", TRUE);
 
        rad_assert(this->used == FALSE);
 
@@ -343,7 +343,7 @@ void fr_connection_pool_delete(fr_connection_pool_t *fc)
                fr_connection_close(fc, this);
        }
 
-       if (fc->trigger) exec_trigger(NULL, fc->cs, "stop");
+       if (fc->trigger) exec_trigger(NULL, fc->cs, "stop", TRUE);
 
        rad_assert(fc->head == NULL);
        rad_assert(fc->tail == NULL);
@@ -446,7 +446,7 @@ fr_connection_pool_t *fr_connection_pool_init(CONF_SECTION *parent,
                }
        }
 
-       if (fc->trigger) exec_trigger(NULL, fc->cs, "start");
+       if (fc->trigger) exec_trigger(NULL, fc->cs, "start", TRUE);
 
        return fc;
 }
index 22f0cf31eaba1af855f458a9b8a70ea430062a5d..16155d87693bc9a383267477176d20048949208a 100644 (file)
@@ -741,7 +741,12 @@ int radius_exec_program(const char *cmd, REQUEST *request,
        return 1;
 }
 
-void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name)
+static void time_free(void *data)
+{
+       free(data);
+}
+
+void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name, int quench)
 {
        CONF_SECTION *subcs;
        CONF_ITEM *ci;
@@ -810,6 +815,34 @@ void exec_trigger(REQUEST *request, CONF_SECTION *cs, const char *name)
        vp = NULL;
        if (request && request->packet) vp = request->packet->vps;
 
+       /*
+        *      Perform periodic quenching.
+        */
+       if (quench) {
+               time_t *last_time;
+
+               last_time = cf_data_find(cs, value);
+               if (!last_time) {
+                       last_time = rad_malloc(sizeof(*last_time));
+                       *last_time = 0;
+
+                       if (cf_data_add(cs, value, last_time, time_free) < 0) {
+                               free(last_time);
+                               last_time = NULL;
+                       }
+               }
+
+               /*
+                *      Send the quenched traps at most once per second.
+                */
+               if (last_time) {
+                       time_t now = time(NULL);
+                       if (*last_time == now) return;
+
+                       *last_time = now;
+               }
+       }
+
        DEBUG("Trigger %s -> %s", name, value);
        radius_exec_program(value, request, 0, NULL, 0, vp, NULL, 1);
 }
index 4bbf940a7f8ee1fd8ef49a364a1814314f997d27..fd9d902e92983684fc899be8b13a8927b2e0e57d 100644 (file)
@@ -300,7 +300,7 @@ RADCLIENT *client_listener_find(rad_listen_t *listener,
        }
 
        request->server = client->server;
-       exec_trigger(request, NULL, "server.client.add");
+       exec_trigger(request, NULL, "server.client.add", FALSE);
 
        request_free(&request);
 
index 710534d8097688dc71a041f67247c2edcb580408..353d4587cbe4ea4f18184e80a8bd1c6fb4f0da12 100644 (file)
@@ -646,7 +646,7 @@ static void request_process_timer(REQUEST *request)
                                       request->number,
                                       request->component ? request->component : "<server core>",
                               request->module ? request->module : "<server core>");
-                               exec_trigger(request, NULL, "server.thread.unresponsive");
+                               exec_trigger(request, NULL, "server.thread.unresponsive", TRUE);
                        }
 #endif
 
@@ -1280,22 +1280,13 @@ int request_receive(rad_listen_t *listener, RADIUS_PACKET *packet,
         */
        if (mainconfig.max_requests &&
            ((count = fr_packet_list_num_elements(pl)) > mainconfig.max_requests)) {
-               static time_t last_complained = 0;
-
                radlog(L_ERR, "Dropping request (%d is too many): from client %s port %d - ID: %d", count,
                       client->shortname,
                       packet->src_port, packet->id);
                radlog(L_INFO, "WARNING: Please check the configuration file.\n"
                       "\tThe value for 'max_requests' is probably set too low.\n");
 
-               /*
-                *      Complain once every 10 seconds.
-                */
-               if ((last_complained + 10) < now.tv_sec) {
-                       last_complained = now.tv_sec;
-                       exec_trigger(NULL, NULL, "server.max_requests");
-               }
-
+               exec_trigger(NULL, NULL, "server.max_requests", TRUE);
                return 0;
        }
 
@@ -2454,7 +2445,7 @@ STATE_MACHINE_DECL(request_ping)
                 *      pings.
                 */
                home->state = HOME_STATE_ALIVE;
-               exec_trigger(request, request->home_server->cs, "home_server.alive");
+               exec_trigger(request, request->home_server->cs, "home_server.alive", FALSE);
                home->currently_outstanding = 0;
                home->num_sent_pings = 0;
                home->num_received_pings = 0;
@@ -2633,7 +2624,7 @@ static void home_trigger(home_server *home, const char *trigger)
        my_packet.dst_ipaddr = home->ipaddr;
        my_packet.src_ipaddr = home->src_ipaddr;
 
-       exec_trigger(&my_request, home->cs, trigger);
+       exec_trigger(&my_request, home->cs, trigger, FALSE);
 }
 
 static void mark_home_server_zombie(home_server *home)
@@ -3792,7 +3783,7 @@ static void handle_signal_self(int flag)
                        fr_event_loop_exit(el, 1);
                } else {
                        radlog(L_INFO, "Signalled to terminate");
-                       exec_trigger(NULL, NULL, "server.signal.term");
+                       exec_trigger(NULL, NULL, "server.signal.term", TRUE);
                        fr_event_loop_exit(el, 2);
                }
 
@@ -3816,7 +3807,7 @@ static void handle_signal_self(int flag)
 
                last_hup = when;
 
-               exec_trigger(NULL, NULL, "server.signal.hup");
+               exec_trigger(NULL, NULL, "server.signal.hup", TRUE);
                fr_event_loop_exit(el, 0x80);
        }
 
index e9cf50fcf049c68d79aa74c8591bbd694d2edd39..6e4dee36c1f867dec81cfa4ed953ed19adf149fd 100644 (file)
@@ -405,7 +405,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       exec_trigger(NULL, NULL, "server.start");
+       exec_trigger(NULL, NULL, "server.start", FALSE);
 
        /*
         *      Process requests until HUP or exit.
@@ -425,7 +425,7 @@ int main(int argc, char *argv[])
                radlog(L_INFO, "Exiting normally.");
        }
 
-       exec_trigger(NULL, NULL, "server.stop");
+       exec_trigger(NULL, NULL, "server.stop", FALSE);
 
        /*
         *      Ignore the TERM signal: we're
index 8f2966cab6ed5b5b991d86de64d52c3594934d37..eb73acdc4bf0729edd6eaf49f38dbcb5983a90e9 100644 (file)
@@ -2294,7 +2294,7 @@ home_server *home_server_ldb(const char *realmname,
                 */
                if ((pool->time_all_dead + 3600) < request->timestamp) {
                        pool->time_all_dead = request->timestamp;
-                       exec_trigger(request, pool->cs, "home_server_pool.fallback");
+                       exec_trigger(request, pool->cs, "home_server_pool.fallback", FALSE);
                }
        }
 
@@ -2302,7 +2302,7 @@ home_server *home_server_ldb(const char *realmname,
        update_and_return:
                if ((found != pool->fallback) && pool->in_fallback) {
                        pool->in_fallback = FALSE;
-                       exec_trigger(request, pool->cs, "home_server_pool.normal");
+                       exec_trigger(request, pool->cs, "home_server_pool.normal", FALSE);
                }
 
                /*
index 9bc68d5038d1a389b7eb96c4fe9fae742344c7e0..51e74fd1460b2bf69c6bbce6621e68b70b140009 100644 (file)
@@ -654,7 +654,7 @@ static void *request_handler_thread(void *arg)
         */
        self->request = NULL;
        self->status = THREAD_EXITED;
-       exec_trigger(NULL, NULL, "server.thread.stop");
+       exec_trigger(NULL, NULL, "server.thread.stop", TRUE);
 
        return NULL;
 }
@@ -721,7 +721,7 @@ static THREAD_HANDLE *spawn_thread(time_t now, int do_trigger)
         */
        if (thread_pool.total_threads >= thread_pool.max_threads) {
                DEBUG2("Thread spawn failed.  Maximum number of threads (%d) already running.", thread_pool.max_threads);
-               exec_trigger(NULL, NULL, "server.thread.max_threads");
+               exec_trigger(NULL, NULL, "server.thread.max_threads", TRUE);
                return NULL;
        }
 
@@ -769,7 +769,7 @@ static THREAD_HANDLE *spawn_thread(time_t now, int do_trigger)
        thread_pool.total_threads++;
        DEBUG2("Thread spawned new child %d. Total threads in pool: %d",
                        handle->thread_num, thread_pool.total_threads);
-       if (do_trigger) exec_trigger(NULL, NULL, "server.thread.start");
+       if (do_trigger) exec_trigger(NULL, NULL, "server.thread.start", TRUE);
 
        /*
         *      Add the thread handle to the tail of the thread pool list.
index e6941ca253c417506217e6560608866ca97472c9..522bcf27ae1c60e7697d33d3b9304433e0de55ef 100644 (file)
@@ -110,14 +110,14 @@ static int valuepair2str(char * out,int outlen,VALUE_PAIR * pair,
        return strlen(out);
 }
 
-static VALUE_PAIR *pairfind_tag(VALUE_PAIR *vps, int attr, int tag)
+static VALUE_PAIR *pairfind_tag(VALUE_PAIR *vps, const DICT_ATTR *da, int tag)
 {
        VALUE_PAIR *vp = vps;
 
 redo:
        if (!vp) return NULL;
 
-       vp = pairfind(vp, attr);
+       vp = pairfind(vp, da->attr, da->vendor);
        if (!tag) return vp;
 
        if (!vp->flags.has_tag) return NULL;
@@ -271,7 +271,7 @@ static size_t xlat_packet(void *instance, REQUEST *request,
                 *      No array, print the tagged attribute.
                 */
                if (!do_array) {
-                       vp = pairfind_tag(vps, da->attr, tag);
+                       vp = pairfind_tag(vps, da, tag);
                        goto just_print;
                }
 
@@ -281,9 +281,9 @@ static size_t xlat_packet(void *instance, REQUEST *request,
                 *      Array[#] - return the total
                 */
                if (do_count) {
-                       for (vp = pairfind_tag(vps, da->attr, tag);
+                       for (vp = pairfind_tag(vps, da, tag);
                             vp != NULL;
-                            vp = pairfind_tag(vp->next, da->attr, tag)) {
+                            vp = pairfind_tag(vp->next, da, tag)) {
                                total++;
                        }
 
@@ -296,9 +296,9 @@ static size_t xlat_packet(void *instance, REQUEST *request,
                 *      the attributes, separated by a newline.
                 */
                if (do_all) {
-                       for (vp = pairfind_tag(vps, da->attr, tag);
+                       for (vp = pairfind_tag(vps, da, tag);
                             vp != NULL;
-                            vp = pairfind_tag(vp->next, da->attr, tag)) {
+                            vp = pairfind_tag(vp->next, da, tag)) {
                                count = valuepair2str(out, outlen - 1, vp, da->type, func);
                                rad_assert(count <= outlen);
                                total += count + 1;
@@ -317,9 +317,9 @@ static size_t xlat_packet(void *instance, REQUEST *request,
                /*
                 *      Find the N'th value.
                 */
-               for (vp = pairfind_tag(vps, da->attr, tag);
+               for (vp = pairfind_tag(vps, da, tag);
                     vp != NULL;
-                    vp = pairfind_tag(vp->next, da->attr, tag)) {
+                    vp = pairfind_tag(vp->next, da, tag)) {
                        if (total == count) break;
                        total++;
                        if (total > count) {
index 19ef5713718b255ba581440ff957de4a618682a6..0600ac1e02aafa5e9778b46b77b4becc07bc897f 100644 (file)
@@ -896,6 +896,7 @@ retry:
                ldap_msgfree(*result);
                return RLM_MODULE_FAIL;
        case LDAP_TIMEOUT:
+               exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
                radlog(L_ERR, "  [%s] ldap_search() failed: Timed out while waiting for server to respond. Please increase the timeout.", inst->xlat_name);
                ldap_msgfree(*result);
                return RLM_MODULE_FAIL;
@@ -904,6 +905,8 @@ retry:
                ldap_msgfree(*result);
                return RLM_MODULE_FAIL;
        case LDAP_TIMELIMIT_EXCEEDED:
+               exec_trigger(NULL, inst->cs, "modules.ldap.timeout", TRUE);
+
        case LDAP_BUSY:
        case LDAP_UNAVAILABLE:
                /* We don't need to reconnect in these cases so we don't set conn->bound */
@@ -2225,7 +2228,7 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password,
 #ifdef HAVE_LDAP_INITIALIZE
                DEBUG("  [%s] (re)connect to %s, authentication %d", inst->xlat_name, inst->server, auth);
                if (ldap_initialize(&ld, inst->server) != LDAP_SUCCESS) {
-                       exec_trigger(NULL, inst->cs, "modules.ldap.fail");
+                       exec_trigger(NULL, inst->cs, "modules.ldap.fail", FALSE);
                        radlog(L_ERR, "  [%s] ldap_initialize() failed", inst->xlat_name);
                        *result = RLM_MODULE_FAIL;
                        return (NULL);
@@ -2234,7 +2237,7 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password,
        } else {
                DEBUG("  [%s] (re)connect to %s:%d, authentication %d", inst->xlat_name, inst->server, inst->port, auth);
                if ((ld = ldap_init(inst->server, inst->port)) == NULL) {
-                       exec_trigger(NULL, inst->cs, "modules.ldap.fail");
+                       exec_trigger(NULL, inst->cs, "modules.ldap.fail", FALSE);
                        radlog(L_ERR, "  [%s] ldap_init() failed", inst->xlat_name);
                        *result = RLM_MODULE_FAIL;
                        return (NULL);
@@ -2430,7 +2433,7 @@ static LDAP *ldap_connect(void *instance, const char *dn, const char *password,
                               ldap_err2string(ldap_errno));
                        *result = RLM_MODULE_FAIL;
                        ldap_unbind_s(ld);
-                       exec_trigger(NULL, inst->cs, "modules.ldap.fail");
+                       exec_trigger(NULL, inst->cs, "modules.ldap.fail", FALSE);
                        return (NULL);
                }
        }
index b688c79749ec457919f710b57730530fb4040346..e7d3d3f3812acc0078ffebb8bdd3a76ecf144b0a 100644 (file)
@@ -51,11 +51,11 @@ static void *sql_conn_create(void *ctx)
 
        rcode = (inst->module->sql_init_socket)(sqlsocket, inst->config);
        if (rcode == 0) {
-               exec_trigger(NULL, inst->cs, "modules.sql.open");
+         exec_trigger(NULL, inst->cs, "modules.sql.open", FALSE);
                return sqlsocket;
        }
 
-       exec_trigger(NULL, inst->cs, "modules.sql.fail");
+       exec_trigger(NULL, inst->cs, "modules.sql.fail", TRUE);
 
        free(sqlsocket);
        return NULL;
@@ -67,7 +67,7 @@ static int sql_conn_delete(void *ctx, void *connection)
        SQL_INST *inst = ctx;
        SQLSOCK *sqlsocket = connection;
 
-       exec_trigger(NULL, inst->cs, "modules.sql.close");
+       exec_trigger(NULL, inst->cs, "modules.sql.close", FALSE);
 
        if (sqlsocket->conn) {
                (inst->module->sql_close)(sqlsocket, inst->config);