|
|
|
|
|
|
|
|
#include <stdint.h> |
|
|
#include <stdint.h> |
|
|
#include <errno.h> |
|
|
#include <errno.h> |
|
|
#include <time.h> |
|
|
#include <time.h> |
|
|
|
|
|
#include <stdarg.h> |
|
|
|
|
|
#include <syslog.h> |
|
|
|
|
|
#include <arpa/inet.h> |
|
|
|
|
|
|
|
|
#include <linux/netfilter.h> |
|
|
#include <linux/netfilter.h> |
|
|
#include <libnetfilter_queue/libnetfilter_queue.h> |
|
|
#include <libnetfilter_queue/libnetfilter_queue.h> |
|
|
|
|
|
|
|
|
#include <uthash.h> |
|
|
#include <uthash.h> |
|
|
|
|
|
|
|
|
#include "dhcp_protect.h" |
|
|
#include "dhcp_protect.h" |
|
|
|
|
|
|
|
|
// main function |
|
|
// main function |
|
|
int main(int argc, char **argv) { |
|
|
int main(int argc, char **argv) { |
|
|
char *configfile; |
|
|
char *configfile; |
|
|
dp_conf conf; |
|
|
dp_conf conf; |
|
|
struct nfq_q_handle *qh; |
|
|
|
|
|
|
|
|
|
|
|
if ( argc == 2 ) { |
|
|
if ( argc == 2 ) { |
|
|
configfile = argv[1]; |
|
|
configfile = argv[1]; |
|
|
|
|
|
|
|
|
if ( load_config(&conf, configfile) == NULL ) |
|
|
if ( load_config(&conf, configfile) == NULL ) |
|
|
return EXIT_FAILURE; |
|
|
return EXIT_FAILURE; |
|
|
|
|
|
|
|
|
|
|
|
openlog("dhcp_protect", LOG_PID, LOG_DAEMON); |
|
|
|
|
|
|
|
|
nfq_start(&conf); |
|
|
nfq_start(&conf); |
|
|
|
|
|
|
|
|
return 0; |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// syslog function |
|
|
|
|
|
void dp_log(unsigned char *remoteid, int remoteidlen, char *fmt, ...) { |
|
|
|
|
|
va_list argList; |
|
|
|
|
|
char buf[1000]; |
|
|
|
|
|
int offset = remoteidlen*2; |
|
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
|
|
for(i=0; i<remoteidlen; i++) { |
|
|
|
|
|
sprintf(buf+(i*2), "%02x", remoteid[i]); |
|
|
|
|
|
} |
|
|
|
|
|
buf[offset]=':'; offset++; |
|
|
|
|
|
buf[offset]=' '; offset++; |
|
|
|
|
|
|
|
|
|
|
|
va_start(argList, fmt); |
|
|
|
|
|
vsnprintf(buf+offset, sizeof(buf)-offset-1, fmt, argList); |
|
|
|
|
|
va_end(argList); |
|
|
|
|
|
|
|
|
|
|
|
syslog(LOG_DAEMON|LOG_INFO, "%s", buf); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// start netfilter queue |
|
|
// start netfilter queue |
|
|
void nfq_start(dp_conf *conf) { |
|
|
void nfq_start(dp_conf *conf) { |
|
|
struct nfq_handle *h; |
|
|
struct nfq_handle *h; |
|
|
|
|
|
|
|
|
conf->bltime = atoi(value); |
|
|
conf->bltime = atoi(value); |
|
|
else if ( strcmp(name, "queue")==0 ) |
|
|
else if ( strcmp(name, "queue")==0 ) |
|
|
conf->queue = atoi(value); |
|
|
conf->queue = atoi(value); |
|
|
|
|
|
else if ( strcmp(name, "dryrun")==0 ) |
|
|
|
|
|
conf->dryrun = atoi(value) ? 1 : 0; |
|
|
else |
|
|
else |
|
|
fprintf(stderr,"unknown directive '%s', ignored\n", name); |
|
|
fprintf(stderr,"unknown directive '%s', ignored\n", name); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fprintf(stderr,"max_pkt_per_interval value invalid (min 1, max 1000)\n"); |
|
|
fprintf(stderr,"max_pkt_per_interval value invalid (min 1, max 1000)\n"); |
|
|
error=1; |
|
|
error=1; |
|
|
} |
|
|
} |
|
|
if ( conf->interval < 10 || conf->interval > 60 ) { |
|
|
|
|
|
fprintf(stderr,"interval value invalid (min 10, max 60)\n"); |
|
|
|
|
|
|
|
|
if ( conf->interval < 5 || conf->interval > 900 ) { |
|
|
|
|
|
fprintf(stderr,"interval value invalid (min 5, max 900)\n"); |
|
|
error=1; |
|
|
error=1; |
|
|
} |
|
|
} |
|
|
if ( conf->debug < 0 || conf->debug > 1 ) { |
|
|
if ( conf->debug < 0 || conf->debug > 1 ) { |
|
|
|
|
|
|
|
|
fprintf(stderr,"queue must be a positive integer\n"); |
|
|
fprintf(stderr,"queue must be a positive integer\n"); |
|
|
error=1; |
|
|
error=1; |
|
|
} |
|
|
} |
|
|
|
|
|
if ( conf->dryrun < 0 || conf->dryrun > 1 ) { |
|
|
|
|
|
fprintf(stderr, "dryrun value invalid (0 or 1)\n"); |
|
|
|
|
|
error=1; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if ( error ) |
|
|
if ( error ) |
|
|
return NULL; |
|
|
return NULL; |
|
|
|
|
|
|
|
|
printf("Configuration:\n"); |
|
|
printf("Configuration:\n"); |
|
|
|
|
|
printf("\t%-20s = %4s\n", "dryrun", conf->dryrun ? "Yes" : "No"); |
|
|
|
|
|
printf("\t%-20s = %4s\n", "debug", conf->debug ? "Yes" : "No" ); |
|
|
|
|
|
printf("\t%-20s = %4is\n", "interval", conf->interval); |
|
|
printf("\t%-20s = %4i\n", "max_pkt_per_interval", conf->pktint); |
|
|
printf("\t%-20s = %4i\n", "max_pkt_per_interval", conf->pktint); |
|
|
printf("\t%-20s = %4i\n", "interval", conf->interval); |
|
|
|
|
|
printf("\t%-20s = %4i\n", "debug", conf->debug); |
|
|
|
|
|
printf("\t%-20s = %4i\n", "blacklist_time", conf->bltime); |
|
|
|
|
|
|
|
|
printf("\t%-20s = %4is\n", "blacklist_time", conf->bltime); |
|
|
printf("\t%-20s = %4i\n", "queue", conf->queue); |
|
|
printf("\t%-20s = %4i\n", "queue", conf->queue); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// decode dhcp packet |
|
|
// decode dhcp packet |
|
|
u_int32_t dhcp_check(struct nfq_data *nfa, int *verdict, dp_conf *conf) { |
|
|
|
|
|
|
|
|
int dhcp_check(struct nfq_data *nfa, dp_conf *conf) { |
|
|
unsigned char *pkt; |
|
|
unsigned char *pkt; |
|
|
int pktlen; |
|
|
int pktlen; |
|
|
int offset = 0; |
|
|
int offset = 0; |
|
|
|
|
|
|
|
|
int found = 0; |
|
|
int found = 0; |
|
|
uint8_t ipver = 0; |
|
|
uint8_t ipver = 0; |
|
|
uint8_t ihl = 0; |
|
|
uint8_t ihl = 0; |
|
|
int i; |
|
|
|
|
|
|
|
|
//int i; |
|
|
|
|
|
int rv = NF_ACCEPT; |
|
|
|
|
|
|
|
|
pktlen = nfq_get_payload(nfa, &pkt); |
|
|
pktlen = nfq_get_payload(nfa, &pkt); |
|
|
|
|
|
|
|
|
for(i=0; i<pktlen; i++) { |
|
|
|
|
|
if ( !(i%16) ) printf("\n"); |
|
|
|
|
|
printf("%02x ", pkt[i]); |
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("got a packet, len = %i\n", pktlen); |
|
|
|
|
|
|
|
|
|
|
|
/* a bit too much ;) |
|
|
|
|
|
if ( conf->debug ) { |
|
|
|
|
|
for(i=0; i<pktlen; i++) { |
|
|
|
|
|
if ( !(i%16) ) printf("\n"); |
|
|
|
|
|
printf("%02x ", pkt[i]); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
// can we read the IP proto and IP header length ? |
|
|
// can we read the IP proto and IP header length ? |
|
|
if ( pktlen > 0 ) { |
|
|
if ( pktlen > 0 ) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( ipver != 4 ) { |
|
|
if ( ipver != 4 ) { |
|
|
if ( conf->debug ) printf("not an IPv4 packet\n"); |
|
|
if ( conf->debug ) printf("not an IPv4 packet\n"); |
|
|
return NF_ACCEPT; |
|
|
|
|
|
|
|
|
rv = NF_ACCEPT; |
|
|
|
|
|
goto end; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// jump over the IPv4 header |
|
|
// jump over the IPv4 header |
|
|
|
|
|
|
|
|
// minimum packet size, fixed header + magic cookie (4 octets) |
|
|
// minimum packet size, fixed header + magic cookie (4 octets) |
|
|
if ( pktlen < offset + 4 ) { |
|
|
if ( pktlen < offset + 4 ) { |
|
|
if ( conf->debug ) printf("packet too small\n"); |
|
|
if ( conf->debug ) printf("packet too small\n"); |
|
|
return NF_ACCEPT; |
|
|
|
|
|
|
|
|
rv = NF_ACCEPT; |
|
|
|
|
|
goto end; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// check magic cookie |
|
|
// check magic cookie |
|
|
if ( pkt[offset] != 99 || pkt[offset+1] != 130 || pkt[offset+2] != 83 || pkt[offset+3] != 99 ) { |
|
|
if ( pkt[offset] != 99 || pkt[offset+1] != 130 || pkt[offset+2] != 83 || pkt[offset+3] != 99 ) { |
|
|
if ( conf->debug ) printf("invalid magic cookie %02x%02x%02x%02x\n", pkt[offset], pkt[offset+1], pkt[offset+2], pkt[offset+3]); |
|
|
|
|
|
return NF_ACCEPT; |
|
|
|
|
|
|
|
|
if ( conf->debug ) |
|
|
|
|
|
printf( |
|
|
|
|
|
"invalid magic cookie %02x%02x%02x%02x\n", |
|
|
|
|
|
pkt[offset], pkt[offset+1], |
|
|
|
|
|
pkt[offset+2], pkt[offset+3]); |
|
|
|
|
|
|
|
|
|
|
|
rv = NF_ACCEPT; |
|
|
|
|
|
goto end; |
|
|
} |
|
|
} |
|
|
offset+=4; |
|
|
offset+=4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
offset++; |
|
|
offset++; |
|
|
|
|
|
|
|
|
printf("type : %i\n",type); |
|
|
|
|
|
|
|
|
// printf("type : %i\n",type); |
|
|
|
|
|
|
|
|
// padding of 1 octet |
|
|
// padding of 1 octet |
|
|
if ( type == 0 ) { |
|
|
if ( type == 0 ) { |
|
|
|
|
|
|
|
|
len = pkt[offset]; |
|
|
len = pkt[offset]; |
|
|
offset++; |
|
|
offset++; |
|
|
|
|
|
|
|
|
printf("len : %i\n", len); |
|
|
|
|
|
|
|
|
// printf("len : %i\n", len); |
|
|
|
|
|
|
|
|
// can the value be read |
|
|
// can the value be read |
|
|
if ( offset+len>=pktlen ) |
|
|
if ( offset+len>=pktlen ) |
|
|
|
|
|
|
|
|
uint8_t olen = o82[o82off+1]; |
|
|
uint8_t olen = o82[o82off+1]; |
|
|
o82off+=2; |
|
|
o82off+=2; |
|
|
|
|
|
|
|
|
printf("o82 type=%i len=%i\n", otype, olen); |
|
|
|
|
|
|
|
|
// printf("o82 type=%i len=%i\n", otype, olen); |
|
|
|
|
|
|
|
|
// remoteid |
|
|
// remoteid |
|
|
if ( otype == 2 ) { |
|
|
if ( otype == 2 ) { |
|
|
// make sure we don't overflow and can read all data |
|
|
// make sure we don't overflow and can read all data |
|
|
if ( o82off + olen > len ) { |
|
|
if ( o82off + olen > len ) { |
|
|
if ( conf->debug) printf("option 82.2 data too long\n"); |
|
|
if ( conf->debug) printf("option 82.2 data too long\n"); |
|
|
return NF_ACCEPT; |
|
|
|
|
|
|
|
|
rv = NF_ACCEPT; |
|
|
|
|
|
goto end; |
|
|
} |
|
|
} |
|
|
else { |
|
|
else { |
|
|
remoteid = o82 + o82off; |
|
|
remoteid = o82 + o82off; |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if ( found ) { |
|
|
if ( found ) { |
|
|
dp_blacklist_count(conf, remoteid, remoteidlen); |
|
|
|
|
|
if ( dp_blacklist_check(conf, remoteid, remoteidlen) ) |
|
|
|
|
|
return NF_ACCEPT; |
|
|
|
|
|
else |
|
|
|
|
|
return NF_DROP; |
|
|
|
|
|
|
|
|
// count the packet, even when blacklisted. |
|
|
|
|
|
dp_accounting_add(conf, remoteid, remoteidlen); |
|
|
|
|
|
|
|
|
|
|
|
// check if already in the blacklist |
|
|
|
|
|
if ( dp_blacklist_check(conf, remoteid, remoteidlen) == NF_DROP ) |
|
|
|
|
|
rv = NF_DROP; |
|
|
|
|
|
|
|
|
|
|
|
// check if it must be added to the blacklist |
|
|
|
|
|
else if ( dp_accounting_check(conf, remoteid, remoteidlen) == NF_DROP ) { |
|
|
|
|
|
dp_blacklist_add(conf, remoteid, remoteidlen); |
|
|
|
|
|
rv = NF_DROP; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
printf("got a packet, len = %i\n", pktlen); |
|
|
|
|
|
return NF_ACCEPT; |
|
|
|
|
|
|
|
|
end: |
|
|
|
|
|
|
|
|
|
|
|
dp_hash_cleanup(conf); |
|
|
|
|
|
|
|
|
|
|
|
return rv; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// netfilter queue callback |
|
|
// netfilter queue callback |
|
|
static int dp_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { |
|
|
static int dp_callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { |
|
|
|
|
|
struct nfqnl_msg_packet_hdr *ph = nfq_get_msg_packet_hdr(nfa); |
|
|
dp_conf *conf = (dp_conf*)data; |
|
|
dp_conf *conf = (dp_conf*)data; |
|
|
|
|
|
int id; |
|
|
int verdict; |
|
|
int verdict; |
|
|
u_int32_t id = dhcp_check(nfa, &verdict, conf); /* Treat packet */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( ph ) { |
|
|
|
|
|
id = ntohl (ph->packet_id); |
|
|
|
|
|
if ( conf->debug ) printf ("received packet with id %d\n", id); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
verdict = dhcp_check(nfa, conf); /* Treat packet */ |
|
|
|
|
|
|
|
|
|
|
|
// override decision for dryrun |
|
|
|
|
|
if ( conf->dryrun ) |
|
|
|
|
|
verdict = NF_ACCEPT; |
|
|
|
|
|
|
|
|
return nfq_set_verdict(qh, id, verdict, 0, NULL); /* Verdict packet */ |
|
|
return nfq_set_verdict(qh, id, verdict, 0, NULL); /* Verdict packet */ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void dp_blacklist_count(dp_conf *conf, unsigned char *remoteid, int len) { |
|
|
|
|
|
int i; |
|
|
|
|
|
dp_blacklist *bl, *tmp; |
|
|
|
|
|
|
|
|
void dp_accounting_add(dp_conf *conf, unsigned char *remoteid, int len) { |
|
|
|
|
|
//int i; |
|
|
|
|
|
dp_accounting *ac; |
|
|
|
|
|
|
|
|
// does the element already exist |
|
|
// does the element already exist |
|
|
HASH_FIND(hh, blacklists, remoteid, len, bl); |
|
|
|
|
|
|
|
|
HASH_FIND(hh, accountings, remoteid, len, ac); |
|
|
|
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("AC: add item\n"); |
|
|
|
|
|
|
|
|
// found it, increment the counter |
|
|
// found it, increment the counter |
|
|
|
|
|
if ( ac ) { |
|
|
|
|
|
if ( conf->debug ) printf("AC: item found, incrementing\n"); |
|
|
|
|
|
ac->count++; |
|
|
|
|
|
} |
|
|
|
|
|
// not found, create a new one |
|
|
|
|
|
else { |
|
|
|
|
|
if ( conf->debug ) printf("AC: item not found, creating\n"); |
|
|
|
|
|
ac = malloc(sizeof(dp_accounting)); |
|
|
|
|
|
|
|
|
|
|
|
memcpy(ac->remoteid, remoteid, len); |
|
|
|
|
|
ac->len = len; |
|
|
|
|
|
ac->count = 1; |
|
|
|
|
|
|
|
|
|
|
|
HASH_ADD(hh, accountings, remoteid, len, ac); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void dp_blacklist_add(dp_conf *conf, unsigned char *remoteid, int len) { |
|
|
|
|
|
dp_blacklist *bl; |
|
|
|
|
|
|
|
|
|
|
|
// alrady exists? |
|
|
|
|
|
HASH_FIND(hh, blacklists, remoteid, len, bl); |
|
|
|
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("BL: add item\n"); |
|
|
|
|
|
|
|
|
|
|
|
// found an entry, push the expiration further |
|
|
if ( bl ) { |
|
|
if ( bl ) { |
|
|
if ( conf->debug ) printf("BL: item found, incrementing\n"); |
|
|
|
|
|
bl->count++; |
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("BL: item found -> pushing further\n"); |
|
|
|
|
|
bl->expire = time(NULL) + conf->bltime; |
|
|
} |
|
|
} |
|
|
// not found, create a new one |
|
|
// not found, create a new one |
|
|
else { |
|
|
else { |
|
|
|
|
|
if ( conf->debug ) printf("BL: item not found, new entry in BL\n"); |
|
|
|
|
|
dp_log(remoteid, len, "blacklisting started"); |
|
|
bl = malloc(sizeof(dp_blacklist)); |
|
|
bl = malloc(sizeof(dp_blacklist)); |
|
|
|
|
|
|
|
|
memcpy(bl->remoteid, remoteid, len); |
|
|
memcpy(bl->remoteid, remoteid, len); |
|
|
bl->len = len; |
|
|
bl->len = len; |
|
|
bl->count = 1; |
|
|
|
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("BL: item not found, creating\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bl->expire = time(NULL) + conf->bltime; |
|
|
HASH_ADD(hh, blacklists, remoteid, len, bl); |
|
|
HASH_ADD(hh, blacklists, remoteid, len, bl); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
printf("count this remoteid "); |
|
|
|
|
|
for(i=0; i<len; i++) printf("%02x",*(uint8_t*)(remoteid+i)); |
|
|
|
|
|
printf("\n"); |
|
|
|
|
|
|
|
|
void dp_hash_cleanup(dp_conf *conf) { |
|
|
|
|
|
dp_accounting *ac, *actmp; |
|
|
|
|
|
dp_blacklist *bl, *bltmp; |
|
|
|
|
|
|
|
|
// is it time to cleanup the list? |
|
|
// is it time to cleanup the list? |
|
|
if ( dp_timestamp + conf->interval < time(NULL) ) { |
|
|
|
|
|
|
|
|
// cleanup every conf->interval seconds |
|
|
|
|
|
if ( dp_accountingtime + conf->interval < time(NULL) ) { |
|
|
if ( conf->debug ) printf("cleanup interval\n"); |
|
|
if ( conf->debug ) printf("cleanup interval\n"); |
|
|
dp_timestamp = time(NULL); |
|
|
|
|
|
HASH_ITER(hh, blacklists, bl, tmp) { |
|
|
|
|
|
HASH_DEL(blacklists, bl); |
|
|
|
|
|
free(bl); |
|
|
|
|
|
|
|
|
dp_accountingtime = time(NULL); |
|
|
|
|
|
HASH_ITER(hh, accountings, ac, actmp) { |
|
|
|
|
|
HASH_DEL(accountings, ac); |
|
|
|
|
|
free(ac); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// blacklist cleanup check every 1 sec |
|
|
|
|
|
if ( dp_cleanuptime < time(NULL) ) { |
|
|
|
|
|
if ( conf->debug ) printf("cleanup BL\n"); |
|
|
|
|
|
dp_cleanuptime = time(NULL); |
|
|
|
|
|
HASH_ITER(hh, blacklists, bl, bltmp) { |
|
|
|
|
|
if ( bl->expire < time(NULL) ) { |
|
|
|
|
|
dp_log( |
|
|
|
|
|
bl->remoteid, bl->len, |
|
|
|
|
|
"blacklisting ended"); |
|
|
|
|
|
HASH_DEL(blacklists, bl); |
|
|
|
|
|
free(bl); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int dp_accounting_check(dp_conf *conf, unsigned char *remoteid, int len) { |
|
|
|
|
|
dp_accounting *ac; |
|
|
|
|
|
|
|
|
|
|
|
HASH_FIND(hh, accountings, remoteid, len, ac); |
|
|
|
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("AC Check\n"); |
|
|
|
|
|
|
|
|
|
|
|
if ( ac ) { |
|
|
|
|
|
if(conf->debug) printf("AC Check: found item %i > %i ?\n", ac->count, conf->pktint); |
|
|
|
|
|
|
|
|
|
|
|
if ( ac->count > conf->pktint ) { |
|
|
|
|
|
if(conf->debug) printf("flood detected!\n"); |
|
|
|
|
|
return NF_DROP; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
return NF_ACCEPT; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
int dp_blacklist_check(dp_conf *conf, unsigned char *remoteid, int len) { |
|
|
int dp_blacklist_check(dp_conf *conf, unsigned char *remoteid, int len) { |
|
|
dp_blacklist *bl; |
|
|
dp_blacklist *bl; |
|
|
|
|
|
|
|
|
HASH_FIND(hh, blacklists, remoteid, len, bl); |
|
|
HASH_FIND(hh, blacklists, remoteid, len, bl); |
|
|
|
|
|
|
|
|
|
|
|
if ( conf->debug ) printf("BL Check\n"); |
|
|
|
|
|
|
|
|
if ( bl ) { |
|
|
if ( bl ) { |
|
|
if(conf->debug) printf("found item\n"); |
|
|
|
|
|
|
|
|
|
|
|
if ( bl->count > conf->pktint ) { |
|
|
|
|
|
if(conf->debug) printf("flood detected!\n"); |
|
|
|
|
|
|
|
|
if ( bl->expire > time(NULL) ) { |
|
|
|
|
|
if ( conf->debug ) printf("blacklisted!\n"); |
|
|
return NF_DROP; |
|
|
return NF_DROP; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return NF_ACCEPT; |
|
|
} |
|
|
} |