#include /* $NetBSD: throttle.c,v 1.7 2011/03/14 17:18:13 tteras Exp $ */ /* Id: throttle.c,v 1.5 2006/04/05 20:54:50 manubsd Exp */ /* * Copyright (C) 2004 Emmanuel Dreyfus * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include #include #include #include #include #include #include "vmbuf.h" #include "misc.h" #include "plog.h" #include "throttle.h" #include "sockmisc.h" #include "isakmp_var.h" #include "isakmp.h" #include "isakmp_xauth.h" #include "isakmp_cfg.h" #include "gcmalloc.h" static struct throttle_list throttle_list = TAILQ_HEAD_INITIALIZER(throttle_list); struct throttle_entry * throttle_add(addr) struct sockaddr *addr; { struct throttle_entry *te; struct timeval now, penalty; size_t len; len = sizeof(*te) - sizeof(struct sockaddr_storage) + sysdep_sa_len(addr); if ((te = racoon_malloc(len)) == NULL) return NULL; sched_get_monotonic_time(&now); penalty.tv_sec = isakmp_cfg_config.auth_throttle; penalty.tv_usec = 0; timeradd(&now, &penalty, &te->penalty_ends); memcpy(&te->host, addr, sysdep_sa_len(addr)); TAILQ_INSERT_HEAD(&throttle_list, te, next); return te; } int throttle_host(addr, authfail) struct sockaddr *addr; int authfail; { struct throttle_entry *te; struct timeval now, res; int found = 0; if (isakmp_cfg_config.auth_throttle == 0) return 0; sched_get_monotonic_time(&now); restart: RACOON_TAILQ_FOREACH_REVERSE(te, &throttle_list, throttle_list, next) { /* * Remove outdated entries */ if (timercmp(&te->penalty_ends, &now, <)) { TAILQ_REMOVE(&throttle_list, te, next); racoon_free(te); goto restart; } if (cmpsaddr(addr, (struct sockaddr *) &te->host) <= CMPSADDR_WOP_MATCH) { found = 1; break; } } /* * No match, if auth failed, allocate a new throttle entry * give no penalty even on error: this is the first time * and we are indulgent. */ if (!found) { if (authfail) { if ((te = throttle_add(addr)) == NULL) { plog(LLV_ERROR, LOCATION, NULL, "Throttle insertion failed\n"); return isakmp_cfg_config.auth_throttle; } } return 0; } else { /* * We had a match and auth failed, increase penalty. */ if (authfail) { struct timeval remaining, penalty; timersub(&te->penalty_ends, &now, &remaining); penalty.tv_sec = isakmp_cfg_config.auth_throttle; penalty.tv_usec = 0; timeradd(&penalty, &remaining, &res); if (res.tv_sec >= THROTTLE_PENALTY_MAX) { res.tv_sec = THROTTLE_PENALTY_MAX; res.tv_usec = 0; } timeradd(&now, &res, &te->penalty_ends); } } timersub(&te->penalty_ends, &now, &res); return res.tv_sec; }