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);
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 */
}
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;
}
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;
}
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);
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);
}
}
- if (fc->trigger) exec_trigger(NULL, fc->cs, "start");
+ if (fc->trigger) exec_trigger(NULL, fc->cs, "start", TRUE);
return fc;
}
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;
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);
}
}
request->server = client->server;
- exec_trigger(request, NULL, "server.client.add");
+ exec_trigger(request, NULL, "server.client.add", FALSE);
request_free(&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
*/
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;
}
* 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;
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)
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);
}
last_hup = when;
- exec_trigger(NULL, NULL, "server.signal.hup");
+ exec_trigger(NULL, NULL, "server.signal.hup", TRUE);
fr_event_loop_exit(el, 0x80);
}
}
}
- exec_trigger(NULL, NULL, "server.start");
+ exec_trigger(NULL, NULL, "server.start", FALSE);
/*
* Process requests until HUP or exit.
radlog(L_INFO, "Exiting normally.");
}
- exec_trigger(NULL, NULL, "server.stop");
+ exec_trigger(NULL, NULL, "server.stop", FALSE);
/*
* Ignore the TERM signal: we're
*/
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);
}
}
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);
}
/*
*/
self->request = NULL;
self->status = THREAD_EXITED;
- exec_trigger(NULL, NULL, "server.thread.stop");
+ exec_trigger(NULL, NULL, "server.thread.stop", TRUE);
return NULL;
}
*/
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;
}
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.
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;
* 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;
}
* 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++;
}
* 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;
/*
* 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) {
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;
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 */
#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);
} 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);
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);
}
}
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;
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);