mirror of
https://github.com/bol-van/zapret.git
synced 2025-08-10 01:02:03 +03:00
tpws: ipcache
This commit is contained in:
275
tpws/pools.c
275
tpws/pools.c
@@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define DESTROY_STR_POOL(etype, ppool) \
|
||||
etype *elem, *tmp; \
|
||||
@@ -517,3 +518,277 @@ bool port_filters_deny_if_empty(struct port_filters_head *head)
|
||||
if (LIST_FIRST(head)) return true;
|
||||
return pf_parse("0",&pf) && port_filter_add(head,&pf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct blob_item *blob_collection_add(struct blob_collection_head *head)
|
||||
{
|
||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
||||
if (entry)
|
||||
{
|
||||
// insert to the end
|
||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
||||
if (iteml)
|
||||
{
|
||||
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
|
||||
LIST_INSERT_AFTER(iteml, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
struct blob_item *blob_collection_add_blob(struct blob_collection_head *head, const void *data, size_t size, size_t size_reserve)
|
||||
{
|
||||
struct blob_item *entry = calloc(1,sizeof(struct blob_item));
|
||||
if (!entry) return NULL;
|
||||
if (!(entry->data = malloc(size+size_reserve)))
|
||||
{
|
||||
free(entry);
|
||||
return NULL;
|
||||
}
|
||||
if (data) memcpy(entry->data,data,size);
|
||||
entry->size = size;
|
||||
entry->size_buf = size+size_reserve;
|
||||
|
||||
// insert to the end
|
||||
struct blob_item *itemc,*iteml=LIST_FIRST(head);
|
||||
if (iteml)
|
||||
{
|
||||
while ((itemc=LIST_NEXT(iteml,next))) iteml = itemc;
|
||||
LIST_INSERT_AFTER(iteml, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(head, entry, next);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
void blob_collection_destroy(struct blob_collection_head *head)
|
||||
{
|
||||
struct blob_item *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
free(entry->extra);
|
||||
free(entry->extra2);
|
||||
free(entry->data);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
bool blob_collection_empty(const struct blob_collection_head *head)
|
||||
{
|
||||
return !LIST_FIRST(head);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void ipcache_item_touch(ip_cache_item *item)
|
||||
{
|
||||
time(&item->last);
|
||||
}
|
||||
static void ipcache_item_init(ip_cache_item *item)
|
||||
{
|
||||
ipcache_item_touch(item);
|
||||
item->hostname = NULL;
|
||||
}
|
||||
static void ipcache_item_destroy(ip_cache_item *item)
|
||||
{
|
||||
free(item->hostname);
|
||||
}
|
||||
|
||||
static void ipcache4Destroy(ip_cache4 **ipcache)
|
||||
{
|
||||
ip_cache4 *elem, *tmp;
|
||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
||||
{
|
||||
HASH_DEL(*ipcache, elem);
|
||||
ipcache_item_destroy(&elem->data);
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
static void ipcache4Key(ip4if *key, const struct in_addr *a)
|
||||
{
|
||||
memset(key,0,sizeof(*key)); // make sure everything is zero
|
||||
key->addr = *a;
|
||||
}
|
||||
static ip_cache4 *ipcache4Find(ip_cache4 *ipcache, const struct in_addr *a)
|
||||
{
|
||||
ip_cache4 *entry;
|
||||
struct ip4if key;
|
||||
|
||||
ipcache4Key(&key,a);
|
||||
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
|
||||
return entry;
|
||||
}
|
||||
static ip_cache4 *ipcache4Add(ip_cache4 **ipcache, const struct in_addr *a)
|
||||
{
|
||||
// avoid dups
|
||||
ip_cache4 *entry = ipcache4Find(*ipcache,a);
|
||||
if (entry) return entry; // already included
|
||||
|
||||
entry = malloc(sizeof(ip_cache4));
|
||||
if (!entry) return NULL;
|
||||
ipcache4Key(&entry->key,a);
|
||||
|
||||
oom = false;
|
||||
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
|
||||
if (oom) { free(entry); return NULL; }
|
||||
|
||||
ipcache_item_init(&entry->data);
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void ipcache4Print(ip_cache4 *ipcache)
|
||||
{
|
||||
char s_ip[16];
|
||||
time_t now;
|
||||
ip_cache4 *ipc, *tmp;
|
||||
|
||||
time(&now);
|
||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
||||
{
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET, &ipc->key.addr, s_ip, sizeof(s_ip));
|
||||
printf("%s : hostname=%s now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
|
||||
}
|
||||
}
|
||||
|
||||
static void ipcache6Destroy(ip_cache6 **ipcache)
|
||||
{
|
||||
ip_cache6 *elem, *tmp;
|
||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
||||
{
|
||||
HASH_DEL(*ipcache, elem);
|
||||
ipcache_item_destroy(&elem->data);
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
static void ipcache6Key(ip6if *key, const struct in6_addr *a)
|
||||
{
|
||||
memset(key,0,sizeof(*key)); // make sure everything is zero
|
||||
key->addr = *a;
|
||||
}
|
||||
static ip_cache6 *ipcache6Find(ip_cache6 *ipcache, const struct in6_addr *a)
|
||||
{
|
||||
ip_cache6 *entry;
|
||||
ip6if key;
|
||||
|
||||
ipcache6Key(&key,a);
|
||||
HASH_FIND(hh, ipcache, &key, sizeof(key), entry);
|
||||
return entry;
|
||||
}
|
||||
static ip_cache6 *ipcache6Add(ip_cache6 **ipcache, const struct in6_addr *a)
|
||||
{
|
||||
// avoid dups
|
||||
ip_cache6 *entry = ipcache6Find(*ipcache,a);
|
||||
if (entry) return entry; // already included
|
||||
|
||||
entry = malloc(sizeof(ip_cache6));
|
||||
if (!entry) return NULL;
|
||||
ipcache6Key(&entry->key,a);
|
||||
|
||||
oom = false;
|
||||
HASH_ADD(hh, *ipcache, key, sizeof(entry->key), entry);
|
||||
if (oom) { free(entry); return NULL; }
|
||||
|
||||
ipcache_item_init(&entry->data);
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void ipcache6Print(ip_cache6 *ipcache)
|
||||
{
|
||||
char s_ip[40];
|
||||
time_t now;
|
||||
ip_cache6 *ipc, *tmp;
|
||||
|
||||
time(&now);
|
||||
HASH_ITER(hh, ipcache , ipc, tmp)
|
||||
{
|
||||
*s_ip=0;
|
||||
inet_ntop(AF_INET6, &ipc->key.addr, s_ip, sizeof(s_ip));
|
||||
printf("%s : hostname=%s now=last+%llu\n", s_ip, ipc->data.hostname ? ipc->data.hostname : "", (unsigned long long)(now-ipc->data.last));
|
||||
}
|
||||
}
|
||||
|
||||
void ipcacheDestroy(ip_cache *ipcache)
|
||||
{
|
||||
ipcache4Destroy(&ipcache->ipcache4);
|
||||
ipcache6Destroy(&ipcache->ipcache6);
|
||||
}
|
||||
void ipcachePrint(ip_cache *ipcache)
|
||||
{
|
||||
ipcache4Print(ipcache->ipcache4);
|
||||
ipcache6Print(ipcache->ipcache6);
|
||||
}
|
||||
|
||||
ip_cache_item *ipcacheTouch(ip_cache *ipcache, const struct in_addr *a4, const struct in6_addr *a6)
|
||||
{
|
||||
ip_cache4 *ipcache4;
|
||||
ip_cache6 *ipcache6;
|
||||
if (a4)
|
||||
{
|
||||
if ((ipcache4 = ipcache4Add(&ipcache->ipcache4,a4)))
|
||||
{
|
||||
ipcache_item_touch(&ipcache4->data);
|
||||
return &ipcache4->data;
|
||||
}
|
||||
}
|
||||
else if (a6)
|
||||
{
|
||||
if ((ipcache6 = ipcache6Add(&ipcache->ipcache6,a6)))
|
||||
{
|
||||
ipcache_item_touch(&ipcache6->data);
|
||||
return &ipcache6->data;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ipcache4_purge(ip_cache4 **ipcache, time_t lifetime)
|
||||
{
|
||||
ip_cache4 *elem, *tmp;
|
||||
time_t now = time(NULL);
|
||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
||||
{
|
||||
if (now >= (elem->data.last + lifetime))
|
||||
{
|
||||
HASH_DEL(*ipcache, elem);
|
||||
ipcache_item_destroy(&elem->data);
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void ipcache6_purge(ip_cache6 **ipcache, time_t lifetime)
|
||||
{
|
||||
ip_cache6 *elem, *tmp;
|
||||
time_t now = time(NULL);
|
||||
HASH_ITER(hh, *ipcache, elem, tmp)
|
||||
{
|
||||
if (now >= (elem->data.last + lifetime))
|
||||
{
|
||||
HASH_DEL(*ipcache, elem);
|
||||
ipcache_item_destroy(&elem->data);
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
static void ipcache_purge(ip_cache *ipcache, time_t lifetime)
|
||||
{
|
||||
if (lifetime) // 0 = no expire
|
||||
{
|
||||
ipcache4_purge(&ipcache->ipcache4, lifetime);
|
||||
ipcache6_purge(&ipcache->ipcache6, lifetime);
|
||||
}
|
||||
}
|
||||
static time_t ipcache_purge_prev=0;
|
||||
void ipcachePurgeRateLimited(ip_cache *ipcache, time_t lifetime)
|
||||
{
|
||||
time_t now = time(NULL);
|
||||
// do not purge too often to save resources
|
||||
if (ipcache_purge_prev != now)
|
||||
{
|
||||
ipcache_purge(ipcache, lifetime);
|
||||
ipcache_purge_prev = now;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user