1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
|
#include "config.h"
#include <string.h>
#ifndef WINDOWS
#include <netinet/in.h>
#endif
#include "client.h"
#include "conn.h"
#include "diag.h"
#include "memory.h"
#include "netconv.h"
#include "pen.h"
#include "server.h"
client *clients;
int clients_max = 0;
int client_acl;
/* Store client and return index */
int store_client(struct sockaddr_storage *cli)
{
int i;
int empty = -1; /* first empty slot */
int oldest = -1; /* in case we need to recycle */
struct sockaddr_in *si;
struct sockaddr_in6 *si6;
int family = cli->ss_family;
unsigned long ad = 0;
void *ad6 = 0;
if (family == AF_INET) {
si = (struct sockaddr_in *)cli;
ad = si->sin_addr.s_addr;
} else if (family == AF_INET6) {
si6 = (struct sockaddr_in6 *)cli;
ad6 = &si6->sin6_addr;
}
for (i = 0; i < clients_max; i++) {
/* look for client with same family and address */
if (family == clients[i].addr.ss_family) {
if (family == AF_UNIX) break;
if (family == AF_INET) {
si = (struct sockaddr_in *)&clients[i].addr;
if (ad == si->sin_addr.s_addr) break;
}
if (family == AF_INET6) {
si6 = (struct sockaddr_in6 *)&clients[i].addr;
if (!memcmp(ad6, &si6->sin6_addr, sizeof *ad6)) break;
}
}
/* recycle slots of client that haven't been used for some time */
if (tracking_time > 0 && clients[i].last+tracking_time < now) {
/* too old, recycle */
clients[i].last = 0;
}
/* we already have an empty slot but keep looking for known client */
if (empty != -1) continue;
/* remember this empty slot in case we need it later */
if (clients[i].last == 0) {
empty = i;
continue;
}
/* and if we can't find any reusable slot we'll reuse the oldest one */
if (oldest == -1 || (clients[i].last < clients[oldest].last)) {
oldest = i;
}
}
/* reset statistics in case this is a "new" client */
if (i == clients_max) {
if (empty != -1) i = empty;
else i = oldest;
DEBUG(2, "Resetting client stats for slot %d", i);
clients[i].connects = 0;
clients[i].csx = 0;
clients[i].crx = 0;
clients[i].server = NO_SERVER;
}
clients[i].last = now;
clients[i].addr = *cli;
clients[i].connects++;
DEBUG(2, "Client %s has index %d", pen_ntoa(cli), i);
return i;
}
void expand_clienttable(int size)
{
if (size <= clients_max) return; /* nothing to do */
clients = pen_realloc(clients, size*sizeof *clients);
memset(&clients[clients_max], 0, (size-clients_max)*sizeof clients[0]);
clients_max = size;
}
|