2019-11-23 03:40:23 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2019 by John D. Robertson *
|
|
|
|
* john@rrci.com *
|
|
|
|
* *
|
|
|
|
* This program 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 3 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program 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. See the *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License *
|
|
|
|
* along with this program; if not, write to the *
|
|
|
|
* Free Software Foundation, Inc., *
|
|
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
|
|
|
***************************************************************************/
|
2019-11-24 02:22:37 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2019-11-29 02:27:03 +00:00
|
|
|
#include "ban2fail.h"
|
2019-11-23 03:40:23 +00:00
|
|
|
#include "cntry.h"
|
|
|
|
#include "maxoff.h"
|
|
|
|
|
|
|
|
static struct {
|
|
|
|
int is_init;
|
|
|
|
MAP cntry_map,
|
|
|
|
addr_map;
|
|
|
|
} S;
|
|
|
|
|
|
|
|
static void
|
|
|
|
initialize(void)
|
|
|
|
/********************************************************
|
|
|
|
* Perform one-time initializations.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
S.is_init= 1;
|
|
|
|
MAP_constructor(&S.cntry_map, 10, 10);
|
2019-11-29 22:23:16 +00:00
|
|
|
MAP_constructor(&S.addr_map, N_ADDRESSES_HINT/BUCKET_DEPTH_HINT, BUCKET_DEPTH_HINT);
|
2019-11-23 03:40:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Compiler doesn't like that we use integers in place of item pointers */
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
|
|
|
|
#pragma GCC diagnostic push
|
|
|
|
#pragma GCC diagnostic ignored "-Wint-conversion"
|
|
|
|
|
|
|
|
int
|
|
|
|
MAXOFF_allowed(const char *addr)
|
|
|
|
/********************************************************
|
|
|
|
* Returns the maximum number of allowed offenses.
|
|
|
|
* -1 means unlimited.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
if(!S.is_init)
|
|
|
|
initialize();
|
|
|
|
|
|
|
|
/* Default is no offenses allowed */
|
|
|
|
int rtn= 0;
|
|
|
|
|
|
|
|
/* Check for by-address specification */
|
|
|
|
rtn= MAP_findStrItem(&S.addr_map, addr);
|
|
|
|
|
|
|
|
/* by-address spec trumps by-country spec */
|
|
|
|
if(!rtn) {
|
|
|
|
const char *cntry;
|
|
|
|
cntry= COUNTRY_get_code(addr);
|
|
|
|
/* if the source country of an address is not known,
|
|
|
|
* then it will be keyed in our map under "unknown".
|
|
|
|
*/
|
|
|
|
cntry= cntry ? cntry : "unknown";
|
|
|
|
rtn= MAP_findStrItem(&S.cntry_map, cntry);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rtn;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2019-11-24 02:22:37 +00:00
|
|
|
MAXOFF_init(CFGMAP *h_cfgmap, char *pfix)
|
2019-11-23 03:40:23 +00:00
|
|
|
/**************************************************************
|
|
|
|
* Initialize objects from configuration map.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
if(!S.is_init)
|
|
|
|
initialize();
|
|
|
|
|
|
|
|
int rtn= -1;
|
|
|
|
|
|
|
|
size_t len= strlen(pfix)+1024;
|
|
|
|
char symBuf[len];
|
2019-11-24 02:22:37 +00:00
|
|
|
unsigned arr_sz= CFGMAP_numTuples(h_cfgmap);
|
2019-11-23 03:40:23 +00:00
|
|
|
struct CFGMAP_tuple rtn_arr[arr_sz];
|
|
|
|
int nAllowed;
|
|
|
|
|
|
|
|
/* Get the allowed number from pfix */
|
|
|
|
const char *str= strrchr(pfix, '\\');
|
|
|
|
++str;
|
|
|
|
if(1 != sscanf(str, "%d", &nAllowed)) {
|
|
|
|
eprintf("ERROR: \"%s\" is not an integer number.", str);
|
|
|
|
goto abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
{ /*--- Register IP entries ---*/
|
|
|
|
snprintf(symBuf, len, "%s\\IP", pfix);
|
|
|
|
|
2019-11-24 02:22:37 +00:00
|
|
|
unsigned nFound= CFGMAP_find_tuples(h_cfgmap, rtn_arr, symBuf);
|
2019-11-23 03:40:23 +00:00
|
|
|
for(unsigned i= 0; i < nFound; ++i) {
|
|
|
|
const struct CFGMAP_tuple *tpl= rtn_arr + i;
|
|
|
|
|
2019-11-24 02:22:37 +00:00
|
|
|
/* Break the address into prefix & subnet bits */
|
|
|
|
static char addr[43];
|
|
|
|
unsigned bits;
|
|
|
|
|
|
|
|
int rc= sscanf(tpl->value, "%42[0-9a-zA-Z:.]/%u", addr, &bits);
|
|
|
|
|
|
|
|
if(1 != rc && 2 != rc) {
|
|
|
|
eprintf("ERROR: \"%s\" is neither IP address or CIDR.", tpl->value);
|
|
|
|
goto abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If it's simply an IP address, place in map & keep going */
|
|
|
|
if(1 == rc) {
|
|
|
|
/* Place in the map the number allowed as if it were
|
|
|
|
* a pointer to an object (there is no object in this case).
|
|
|
|
*/
|
|
|
|
MAP_addStrKey(&S.addr_map, addr, (void*)nAllowed);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Avoid stupidity right off the hop */
|
|
|
|
if(strchr(addr, ':')) {
|
|
|
|
eprintf("ERROR: CIDR not implemented for ipv6 \"%s\"", tpl->value);
|
|
|
|
goto abort;
|
|
|
|
} else if(16 > bits) {
|
|
|
|
eprintf("ERROR: Subnet is too large! \"%s\"", tpl->value);
|
|
|
|
goto abort;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--- Expand the CIDR notation to addresses ---*/
|
|
|
|
unsigned q1, q2, q3, q4;
|
|
|
|
|
|
|
|
/* Convert quad values from text to binary */
|
|
|
|
rc= sscanf(addr, "%u.%u.%u.%u", &q1, &q2, &q3, &q4);
|
|
|
|
|
|
|
|
/* Convert quads into useful parameters */
|
|
|
|
uint32_t baddr= (q1 << 24) | (q2 << 16) | (q3 << 8) | q4,
|
|
|
|
mask= 0xffffffff << (32-bits),
|
|
|
|
net= baddr & mask,
|
|
|
|
nAddr= 0xffffffff >> bits;
|
|
|
|
|
|
|
|
assert(4 == rc);
|
|
|
|
|
|
|
|
/* Generate individual addresses, and place them in the map */
|
|
|
|
for(unsigned i= 0; i < nAddr; ++i) {
|
|
|
|
baddr= net | i;
|
|
|
|
q1= (baddr & 0xff000000) >> 24;
|
|
|
|
q2= (baddr & 0x00ff0000) >> 16;
|
|
|
|
q3= (baddr & 0x0000ff00) >> 8;
|
|
|
|
q4= baddr & 0x000000ff;
|
|
|
|
|
|
|
|
/* Convert back to text form */
|
|
|
|
snprintf(addr, sizeof(addr), "%u.%u.%u.%u", q1, q2, q3, q4);
|
|
|
|
/* Add to the map */
|
|
|
|
MAP_addStrKey(&S.addr_map, addr, (void*)nAllowed);
|
|
|
|
}
|
2019-11-23 03:40:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{ /*--- Register COUNTRY entries ---*/
|
|
|
|
snprintf(symBuf, len, "%s\\COUNTRY", pfix);
|
2019-11-24 02:22:37 +00:00
|
|
|
unsigned nFound= CFGMAP_find_tuples(h_cfgmap, rtn_arr, symBuf);
|
2019-11-23 03:40:23 +00:00
|
|
|
|
|
|
|
for(unsigned i= 0; i < nFound; ++i) {
|
|
|
|
const struct CFGMAP_tuple *tpl= rtn_arr + i;
|
|
|
|
|
|
|
|
/* Place in the map the number allowed as if it were
|
|
|
|
* a pointer to an object (superflous in this case).
|
|
|
|
*/
|
|
|
|
MAP_addStrKey(&S.cntry_map, tpl->value, (void*)nAllowed);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rtn= 0;
|
|
|
|
abort:
|
|
|
|
return rtn;
|
|
|
|
}
|
|
|
|
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
#pragma GCC diagnostic pop
|
|
|
|
|