2013-09-16 09:53:25 +00:00
|
|
|
/* This file is part of Netsukuku
|
|
|
|
* (c) Copyright 2005 Andrea Lo Pumo aka AlpT <alpt@freaknet.org>
|
|
|
|
*
|
|
|
|
* This source code is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License as published
|
|
|
|
* by the Free Software Foundation; either version 2 of the License,
|
|
|
|
* or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This source code is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
* Please refer to the GNU Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Public License along with
|
|
|
|
* this source code; if not, write to:
|
|
|
|
* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*
|
|
|
|
* --
|
|
|
|
* accept.c: This is how it works:
|
|
|
|
*
|
|
|
|
* When a new accept is made add_accept is called. It first updates the accept
|
|
|
|
* table and then, if the accept_tbl isn't full add the new accept in the tbl.
|
|
|
|
* If the accept_tbl is full the connection is dropped.
|
|
|
|
* Each accept in the table last for free_accept_time after the close of that
|
|
|
|
* connection, so if an host has fulled the accept_tbl has to wait
|
|
|
|
* free_accept_time of seconds to be able to reconnect again.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "includes.h"
|
|
|
|
|
|
|
|
#include "request.h"
|
|
|
|
#include "inet.h"
|
|
|
|
#include "accept.h"
|
|
|
|
#include "xmalloc.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
void
|
|
|
|
init_accept_tbl(int startups, int accepts, int time)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
/* TODO: activate and test it !! */
|
|
|
|
#if 0
|
|
|
|
int i;
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
max_connections = startups;
|
|
|
|
max_accepts_per_host = accepts;
|
|
|
|
free_accept_time = time;
|
|
|
|
accept_idx = accept_sidx = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
pthread_mutex_init(&mtx_acpt_idx, NULL);
|
|
|
|
pthread_mutex_init(&mtx_acpt_sidx, NULL);
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
accept_tbl =
|
|
|
|
(struct accept_table *) xmalloc(sizeof(struct accept_table) *
|
|
|
|
max_connections);
|
|
|
|
memset(accept_tbl, '\0',
|
|
|
|
sizeof(struct accept_table) * max_connections);
|
|
|
|
|
|
|
|
for (i = 0; i < max_connections; i++) {
|
|
|
|
accept_tbl[i].pid =
|
|
|
|
(pid_t *) xmalloc(sizeof(pid_t) * max_accepts_per_host);
|
|
|
|
memset(accept_tbl[i].pid, '\0',
|
|
|
|
sizeof(pid_t) * max_accepts_per_host);
|
|
|
|
|
|
|
|
accept_tbl[i].closed =
|
|
|
|
(unsigned char *) xmalloc(sizeof(unsigned char) *
|
|
|
|
max_accepts_per_host);
|
|
|
|
memset(accept_tbl[i].closed, '\0',
|
|
|
|
sizeof(unsigned char) * max_accepts_per_host);
|
|
|
|
|
|
|
|
accept_tbl[i].acp_t =
|
|
|
|
(time_t *) xmalloc(sizeof(time_t) * max_accepts_per_host);
|
|
|
|
memset(accept_tbl[i].acp_t, '\0',
|
|
|
|
sizeof(time_t) * max_accepts_per_host);
|
2013-09-16 09:53:25 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
void
|
|
|
|
destroy_accept_tbl(void)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
/* TODO: activate and test it !! */
|
|
|
|
#if 0
|
2014-09-17 12:41:24 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!accept_tbl)
|
2013-09-16 09:53:25 +00:00
|
|
|
return;
|
2014-09-17 12:41:24 +00:00
|
|
|
for (i = 0; i < max_connections; i++) {
|
2013-09-16 09:53:25 +00:00
|
|
|
xfree(accept_tbl[i].pid);
|
|
|
|
xfree(accept_tbl[i].closed);
|
|
|
|
xfree(accept_tbl[i].acp_t);
|
|
|
|
}
|
|
|
|
xfree(accept_tbl);
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_tbl = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
void
|
|
|
|
update_accept_tbl(void)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
time_t cur_t, passed_time;
|
2014-09-17 12:41:24 +00:00
|
|
|
int i, e, k, ee, pid_exists;
|
|
|
|
|
|
|
|
if (update_accept_tbl_mutex)
|
2013-09-16 09:53:25 +00:00
|
|
|
return;
|
|
|
|
else
|
2014-09-17 12:41:24 +00:00
|
|
|
update_accept_tbl_mutex = 1;
|
|
|
|
|
2013-09-16 09:53:25 +00:00
|
|
|
time(&cur_t);
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
for (i = 0; i < max_connections; i++) {
|
|
|
|
if (!accept_tbl[i].ip.len)
|
2013-09-16 09:53:25 +00:00
|
|
|
continue;
|
2014-09-17 12:41:24 +00:00
|
|
|
if (accept_tbl[i].accepts) {
|
|
|
|
for (e = 0; e < max_accepts_per_host; e++) {
|
|
|
|
if (!accept_tbl[i].acp_t[e])
|
2013-09-16 09:53:25 +00:00
|
|
|
continue;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
if (accept_tbl[i].pid[e]) {
|
|
|
|
k = kill(accept_tbl[i].pid[e], 0);
|
|
|
|
pid_exists = !(k == -1 && errno == ESRCH);
|
2013-09-16 09:53:25 +00:00
|
|
|
} else
|
2014-09-17 12:41:24 +00:00
|
|
|
pid_exists = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
debug(DBG_NOISE, "ACPT: Updating tbl: cur_t: %d, "
|
2014-09-17 12:41:24 +00:00
|
|
|
"accept_tbl[%d].acp_t[%d]:%d+%d, "
|
|
|
|
"accept_tbl[i].pid[e]: %d, "
|
|
|
|
"kill=%d (ESRCH=%d)",
|
|
|
|
cur_t, i, e, accept_tbl[i].acp_t[e],
|
|
|
|
free_accept_time, accept_tbl[i].pid[e], k, ESRCH);
|
2013-09-16 09:53:25 +00:00
|
|
|
#endif
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
passed_time = accept_tbl[i].acp_t[e] + free_accept_time;
|
|
|
|
if ((accept_tbl[i].closed[e] || !pid_exists) &&
|
|
|
|
passed_time <= cur_t) {
|
|
|
|
ee = e;
|
2013-09-16 09:53:25 +00:00
|
|
|
del_accept(i, &ee);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-09-17 12:41:24 +00:00
|
|
|
update_accept_tbl_mutex = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
find_ip_acpt(inet_prefix ip)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
int i;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
for (i = 0; i < max_accepts_per_host; i++) {
|
|
|
|
if (!memcmp(accept_tbl[i].ip.data, &ip.data, MAX_IP_SZ))
|
2013-09-16 09:53:25 +00:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
find_first_free(void)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
int i;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
for (i = 0; i < max_connections; i++)
|
|
|
|
if (!accept_tbl[i].accepts)
|
2013-09-16 09:53:25 +00:00
|
|
|
return i;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
is_ip_acpt_free(inet_prefix ip, int *index)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
int idx;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
2013-09-16 09:53:25 +00:00
|
|
|
update_accept_tbl();
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
if ((idx = find_ip_acpt(ip)) == -1)
|
|
|
|
if ((idx = find_first_free()) == -1)
|
2013-09-16 09:53:25 +00:00
|
|
|
return E_TOO_MANY_CONN;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
2013-09-16 09:53:25 +00:00
|
|
|
/*debug(DBG_NOISE, "ACPT: accept_tbl[%d].accepts: %d, max_acp: %d", idx,
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_tbl[idx].accepts, max_accepts_per_host); */
|
2013-09-16 09:53:25 +00:00
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
if (accept_tbl[idx].accepts >= max_accepts_per_host)
|
2013-09-16 09:53:25 +00:00
|
|
|
return E_ACCEPT_TBL_FULL;
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
*index = idx;
|
2013-09-16 09:53:25 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
find_free_acp_t(int idx)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
int e;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
for (e = 0; e < max_accepts_per_host; e++) {
|
|
|
|
if (!accept_tbl[idx].acp_t[e])
|
2013-09-16 09:53:25 +00:00
|
|
|
return e;
|
|
|
|
}
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
return -1; /*This happens if the rq_tbl is full for the "rq" request */
|
2013-09-16 09:53:25 +00:00
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
new_accept(int idx, inet_prefix ip)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
2014-09-17 12:41:24 +00:00
|
|
|
int cl = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
/* TODO: activate and test it !! */
|
|
|
|
#if 0
|
|
|
|
time_t cur_t;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
2013-09-16 09:53:25 +00:00
|
|
|
time(&cur_t);
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
if ((cl = find_free_acp_t(idx)) == -1)
|
2013-09-16 09:53:25 +00:00
|
|
|
return -1;
|
|
|
|
accept_tbl[idx].accepts++;
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_tbl[idx].acp_t[cl] = cur_t;
|
|
|
|
accept_tbl[idx].closed[cl] = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
inet_copy(&accept_tbl[idx].ip, &ip);
|
|
|
|
#endif
|
|
|
|
return cl;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_accept: It adds a new accept of `ip'. If `replace' is not 0 the `ip's
|
|
|
|
* accepts are not incremented and accept_sidx is set to 0.
|
|
|
|
*/
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
add_accept(inet_prefix ip, int replace)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
/* TODO: activate and test it !! */
|
|
|
|
#if 0
|
|
|
|
int err, idx, cl;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
if ((err = is_ip_acpt_free(ip, &idx)))
|
2013-09-16 09:53:25 +00:00
|
|
|
return err;
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
if (!replace || !accept_tbl[idx].accepts) {
|
|
|
|
cl = new_accept(idx, ip);
|
|
|
|
if (cl < 0)
|
2013-09-16 09:53:25 +00:00
|
|
|
return -1;
|
2014-09-17 12:41:24 +00:00
|
|
|
} else
|
|
|
|
cl = 0;
|
2013-09-16 09:53:25 +00:00
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
/*This global var will be given to the thread */
|
2013-09-16 09:53:25 +00:00
|
|
|
pthread_mutex_lock(&mtx_acpt_idx);
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_idx = idx;
|
2013-09-16 09:53:25 +00:00
|
|
|
pthread_mutex_unlock(&mtx_acpt_idx);
|
|
|
|
|
|
|
|
pthread_mutex_lock(&mtx_acpt_sidx);
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_sidx = cl;
|
2013-09-16 09:53:25 +00:00
|
|
|
pthread_mutex_unlock(&mtx_acpt_sidx);
|
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
void
|
|
|
|
del_accept(int idx, int *sidx)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
#if 0
|
2014-09-17 12:41:24 +00:00
|
|
|
if (!accept_tbl[idx].accepts)
|
2013-09-16 09:53:25 +00:00
|
|
|
return;
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
if (accept_tbl[idx].acp_t[*sidx]) {
|
2013-09-16 09:53:25 +00:00
|
|
|
accept_tbl[idx].accepts--;
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_tbl[idx].acp_t[*sidx] = 0;
|
|
|
|
accept_tbl[idx].closed[*sidx] = 0;
|
|
|
|
if (!accept_tbl[idx].accepts)
|
2013-09-16 09:53:25 +00:00
|
|
|
memset(&accept_tbl[idx].ip, '\0', sizeof(inet_prefix));
|
|
|
|
(*sidx)--;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
int
|
|
|
|
close_accept(int idx, int sidx)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
#if 0
|
2014-09-17 12:41:24 +00:00
|
|
|
if (!accept_tbl[idx].accepts)
|
2013-09-16 09:53:25 +00:00
|
|
|
return -1;
|
2014-09-17 12:41:24 +00:00
|
|
|
|
|
|
|
accept_tbl[idx].closed[sidx] = 1;
|
2013-09-16 09:53:25 +00:00
|
|
|
#endif
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-09-17 12:41:24 +00:00
|
|
|
void
|
|
|
|
add_accept_pid(pid_t pid, int idx, int sidx)
|
2013-09-16 09:53:25 +00:00
|
|
|
{
|
|
|
|
/* TODO: activate and test it !! */
|
|
|
|
#if 0
|
2014-09-17 12:41:24 +00:00
|
|
|
accept_tbl[idx].pid[sidx] = pid;
|
2013-09-16 09:53:25 +00:00
|
|
|
/* debug(DBG_NOISE, "ACPT: Added pig %d in accept_tbl[%d].pid[%d]",
|
|
|
|
accept_tbl[idx].pid[sidx], idx, sidx);
|
|
|
|
*/
|
|
|
|
#endif
|
|
|
|
}
|