mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-24 01:07:21 +01:00
2a63c3be15
Remove /^/[*/]\s*\$FreeBSD\$.*\n/
1038 lines
21 KiB
Plaintext
1038 lines
21 KiB
Plaintext
|
|
/*
|
|
* Copyright (C) 2012 by Darren Reed.
|
|
*
|
|
* See the IPFILTER.LICENCE file for details on licencing.
|
|
*/
|
|
%{
|
|
#include "ipf.h"
|
|
#include <syslog.h>
|
|
#undef OPT_NAT
|
|
#undef OPT_VERBOSE
|
|
#include "ipmon_l.h"
|
|
#include "ipmon.h"
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#define YYDEBUG 1
|
|
|
|
extern void yyerror(char *);
|
|
extern int yyparse(void);
|
|
extern int yylex(void);
|
|
extern int yydebug;
|
|
extern FILE *yyin;
|
|
extern int yylineNum;
|
|
extern int ipmonopts;
|
|
|
|
typedef struct opt_s {
|
|
struct opt_s *o_next;
|
|
int o_line;
|
|
int o_type;
|
|
int o_num;
|
|
char *o_str;
|
|
struct in_addr o_ip;
|
|
int o_logfac;
|
|
int o_logpri;
|
|
} opt_t;
|
|
|
|
static void build_action(opt_t *, ipmon_doing_t *);
|
|
static opt_t *new_opt(int);
|
|
static void free_action(ipmon_action_t *);
|
|
static void print_action(ipmon_action_t *);
|
|
static int find_doing(char *);
|
|
static ipmon_doing_t *build_doing(char *, char *);
|
|
static void print_match(ipmon_action_t *);
|
|
static int install_saver(char *, char *);
|
|
|
|
static ipmon_action_t *alist = NULL;
|
|
|
|
ipmon_saver_int_t *saverlist = NULL;
|
|
%}
|
|
|
|
%union {
|
|
char *str;
|
|
u_32_t num;
|
|
struct in_addr addr;
|
|
struct opt_s *opt;
|
|
union i6addr ip6;
|
|
struct ipmon_doing_s *ipmd;
|
|
}
|
|
|
|
%token <num> YY_NUMBER YY_HEX
|
|
%token <str> YY_STR
|
|
%token <ip6> YY_IPV6
|
|
%token YY_COMMENT
|
|
%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT
|
|
%token YY_RANGE_OUT YY_RANGE_IN
|
|
|
|
%token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT
|
|
%token IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION
|
|
%token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE
|
|
%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH
|
|
%token IPM_DO IPM_DOING IPM_TYPE IPM_NAT
|
|
%token IPM_STATE IPM_NATTAG IPM_IPF
|
|
%type <addr> ipv4
|
|
%type <opt> direction dstip dstport every group interface
|
|
%type <opt> protocol result rule srcip srcport logtag matching
|
|
%type <opt> matchopt nattag type
|
|
%type <num> typeopt
|
|
%type <ipmd> doopt doing
|
|
|
|
%%
|
|
file: action
|
|
| file action
|
|
;
|
|
|
|
action: line ';'
|
|
| assign ';'
|
|
| IPM_COMMENT
|
|
| YY_COMMENT
|
|
;
|
|
|
|
line: IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}'
|
|
{ build_action($3, $8);
|
|
resetlexer();
|
|
}
|
|
| IPM_LOADACTION YY_STR YY_STR { if (install_saver($2, $3))
|
|
yyerror("install saver");
|
|
}
|
|
;
|
|
|
|
assign: YY_STR assigning YY_STR { set_variable($1, $3);
|
|
resetlexer();
|
|
free($1);
|
|
free($3);
|
|
yyvarnext = 0;
|
|
}
|
|
;
|
|
|
|
assigning:
|
|
'=' { yyvarnext = 1; }
|
|
;
|
|
|
|
matching:
|
|
matchopt { $$ = $1; }
|
|
| matchopt ',' matching { $1->o_next = $3; $$ = $1; }
|
|
;
|
|
|
|
matchopt:
|
|
direction { $$ = $1; }
|
|
| dstip { $$ = $1; }
|
|
| dstport { $$ = $1; }
|
|
| every { $$ = $1; }
|
|
| group { $$ = $1; }
|
|
| interface { $$ = $1; }
|
|
| protocol { $$ = $1; }
|
|
| result { $$ = $1; }
|
|
| rule { $$ = $1; }
|
|
| srcip { $$ = $1; }
|
|
| srcport { $$ = $1; }
|
|
| logtag { $$ = $1; }
|
|
| nattag { $$ = $1; }
|
|
| type { $$ = $1; }
|
|
;
|
|
|
|
doing:
|
|
doopt { $$ = $1; }
|
|
| doopt ',' doing { $1->ipmd_next = $3; $$ = $1; }
|
|
;
|
|
|
|
doopt:
|
|
YY_STR { if (find_doing($1) != IPM_DOING)
|
|
yyerror("unknown action");
|
|
}
|
|
'(' YY_STR ')' { $$ = build_doing($1, $4);
|
|
if ($$ == NULL)
|
|
yyerror("action building");
|
|
}
|
|
| YY_STR { if (find_doing($1) == IPM_DOING)
|
|
$$ = build_doing($1, NULL);
|
|
}
|
|
;
|
|
|
|
direction:
|
|
IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION);
|
|
$$->o_num = IPM_IN; }
|
|
| IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION);
|
|
$$->o_num = IPM_OUT; }
|
|
;
|
|
|
|
dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP);
|
|
$$->o_ip = $3;
|
|
$$->o_num = $5; }
|
|
;
|
|
|
|
dstport:
|
|
IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT);
|
|
$$->o_num = $3; }
|
|
| IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT);
|
|
$$->o_str = $3; }
|
|
;
|
|
|
|
every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND);
|
|
$$->o_num = 1; }
|
|
| IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND);
|
|
$$->o_num = $2; }
|
|
| IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET);
|
|
$$->o_num = 1; }
|
|
| IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET);
|
|
$$->o_num = $2; }
|
|
;
|
|
|
|
group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP);
|
|
$$->o_num = $3; }
|
|
| IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP);
|
|
$$->o_str = $3; }
|
|
;
|
|
|
|
interface:
|
|
IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE);
|
|
$$->o_str = $3; }
|
|
;
|
|
|
|
logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG);
|
|
$$->o_num = $3; }
|
|
;
|
|
|
|
nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG);
|
|
$$->o_str = $3; }
|
|
;
|
|
|
|
protocol:
|
|
IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL);
|
|
$$->o_num = $3; }
|
|
| IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL);
|
|
$$->o_num = getproto($3);
|
|
free($3);
|
|
}
|
|
;
|
|
|
|
result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT);
|
|
$$->o_str = $3; }
|
|
;
|
|
|
|
rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE);
|
|
$$->o_num = YY_NUMBER; }
|
|
;
|
|
|
|
srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP);
|
|
$$->o_ip = $3;
|
|
$$->o_num = $5; }
|
|
;
|
|
|
|
srcport:
|
|
IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT);
|
|
$$->o_num = $3; }
|
|
| IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT);
|
|
$$->o_str = $3; }
|
|
;
|
|
|
|
type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE);
|
|
$$->o_num = $3; }
|
|
;
|
|
|
|
typeopt:
|
|
IPM_IPF { $$ = IPL_MAGIC; }
|
|
| IPM_NAT { $$ = IPL_MAGIC_NAT; }
|
|
| IPM_STATE { $$ = IPL_MAGIC_STATE; }
|
|
;
|
|
|
|
|
|
|
|
ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER
|
|
{ if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) {
|
|
yyerror("Invalid octet string for IP address");
|
|
return(0);
|
|
}
|
|
$$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7;
|
|
$$.s_addr = htonl($$.s_addr);
|
|
}
|
|
%%
|
|
static struct wordtab yywords[] = {
|
|
{ "body", IPM_BODY },
|
|
{ "direction", IPM_DIRECTION },
|
|
{ "do", IPM_DO },
|
|
{ "dstip", IPM_DSTIP },
|
|
{ "dstport", IPM_DSTPORT },
|
|
{ "every", IPM_EVERY },
|
|
{ "group", IPM_GROUP },
|
|
{ "in", IPM_IN },
|
|
{ "interface", IPM_INTERFACE },
|
|
{ "ipf", IPM_IPF },
|
|
{ "load_action",IPM_LOADACTION },
|
|
{ "logtag", IPM_LOGTAG },
|
|
{ "match", IPM_MATCH },
|
|
{ "nat", IPM_NAT },
|
|
{ "nattag", IPM_NATTAG },
|
|
{ "no", IPM_NO },
|
|
{ "out", IPM_OUT },
|
|
{ "packet", IPM_PACKET },
|
|
{ "packets", IPM_PACKETS },
|
|
{ "protocol", IPM_PROTOCOL },
|
|
{ "result", IPM_RESULT },
|
|
{ "rule", IPM_RULE },
|
|
{ "second", IPM_SECOND },
|
|
{ "seconds", IPM_SECONDS },
|
|
{ "srcip", IPM_SRCIP },
|
|
{ "srcport", IPM_SRCPORT },
|
|
{ "state", IPM_STATE },
|
|
{ "with", IPM_WITH },
|
|
{ NULL, 0 }
|
|
};
|
|
|
|
static int macflags[17][2] = {
|
|
{ IPM_DIRECTION, IPMAC_DIRECTION },
|
|
{ IPM_DSTIP, IPMAC_DSTIP },
|
|
{ IPM_DSTPORT, IPMAC_DSTPORT },
|
|
{ IPM_GROUP, IPMAC_GROUP },
|
|
{ IPM_INTERFACE, IPMAC_INTERFACE },
|
|
{ IPM_LOGTAG, IPMAC_LOGTAG },
|
|
{ IPM_NATTAG, IPMAC_NATTAG },
|
|
{ IPM_PACKET, IPMAC_EVERY },
|
|
{ IPM_PROTOCOL, IPMAC_PROTOCOL },
|
|
{ IPM_RESULT, IPMAC_RESULT },
|
|
{ IPM_RULE, IPMAC_RULE },
|
|
{ IPM_SECOND, IPMAC_EVERY },
|
|
{ IPM_SRCIP, IPMAC_SRCIP },
|
|
{ IPM_SRCPORT, IPMAC_SRCPORT },
|
|
{ IPM_TYPE, IPMAC_TYPE },
|
|
{ IPM_WITH, IPMAC_WITH },
|
|
{ 0, 0 }
|
|
};
|
|
|
|
static opt_t *
|
|
new_opt(int type)
|
|
{
|
|
opt_t *o;
|
|
|
|
o = (opt_t *)calloc(1, sizeof(*o));
|
|
o->o_type = type;
|
|
o->o_line = yylineNum;
|
|
o->o_logfac = -1;
|
|
o->o_logpri = -1;
|
|
return(o);
|
|
}
|
|
|
|
static void
|
|
build_action(opt_t *olist, ipmon_doing_t *todo)
|
|
{
|
|
ipmon_action_t *a;
|
|
opt_t *o;
|
|
int i;
|
|
|
|
a = (ipmon_action_t *)calloc(1, sizeof(*a));
|
|
if (a == NULL)
|
|
return;
|
|
|
|
while ((o = olist) != NULL) {
|
|
/*
|
|
* Check to see if the same comparator is being used more than
|
|
* once per matching statement.
|
|
*/
|
|
for (i = 0; macflags[i][0]; i++)
|
|
if (macflags[i][0] == o->o_type)
|
|
break;
|
|
if (macflags[i][1] & a->ac_mflag) {
|
|
fprintf(stderr, "%s redfined on line %d\n",
|
|
yykeytostr(o->o_type), yylineNum);
|
|
if (o->o_str != NULL)
|
|
free(o->o_str);
|
|
olist = o->o_next;
|
|
free(o);
|
|
continue;
|
|
}
|
|
|
|
a->ac_mflag |= macflags[i][1];
|
|
|
|
switch (o->o_type)
|
|
{
|
|
case IPM_DIRECTION :
|
|
a->ac_direction = o->o_num;
|
|
break;
|
|
case IPM_DSTIP :
|
|
a->ac_dip = o->o_ip.s_addr;
|
|
a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num));
|
|
break;
|
|
case IPM_DSTPORT :
|
|
a->ac_dport = htons(o->o_num);
|
|
break;
|
|
case IPM_INTERFACE :
|
|
a->ac_iface = o->o_str;
|
|
o->o_str = NULL;
|
|
break;
|
|
case IPM_GROUP :
|
|
if (o->o_str != NULL)
|
|
strncpy(a->ac_group, o->o_str, FR_GROUPLEN);
|
|
else
|
|
sprintf(a->ac_group, "%d", o->o_num);
|
|
break;
|
|
case IPM_LOGTAG :
|
|
a->ac_logtag = o->o_num;
|
|
break;
|
|
case IPM_NATTAG :
|
|
strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag));
|
|
break;
|
|
case IPM_PACKET :
|
|
a->ac_packet = o->o_num;
|
|
break;
|
|
case IPM_PROTOCOL :
|
|
a->ac_proto = o->o_num;
|
|
break;
|
|
case IPM_RULE :
|
|
a->ac_rule = o->o_num;
|
|
break;
|
|
case IPM_RESULT :
|
|
if (!strcasecmp(o->o_str, "pass"))
|
|
a->ac_result = IPMR_PASS;
|
|
else if (!strcasecmp(o->o_str, "block"))
|
|
a->ac_result = IPMR_BLOCK;
|
|
else if (!strcasecmp(o->o_str, "nomatch"))
|
|
a->ac_result = IPMR_NOMATCH;
|
|
else if (!strcasecmp(o->o_str, "log"))
|
|
a->ac_result = IPMR_LOG;
|
|
break;
|
|
case IPM_SECOND :
|
|
a->ac_second = o->o_num;
|
|
break;
|
|
case IPM_SRCIP :
|
|
a->ac_sip = o->o_ip.s_addr;
|
|
a->ac_smsk = htonl(0xffffffff << (32 - o->o_num));
|
|
break;
|
|
case IPM_SRCPORT :
|
|
a->ac_sport = htons(o->o_num);
|
|
break;
|
|
case IPM_TYPE :
|
|
a->ac_type = o->o_num;
|
|
break;
|
|
case IPM_WITH :
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
|
|
olist = o->o_next;
|
|
if (o->o_str != NULL)
|
|
free(o->o_str);
|
|
free(o);
|
|
}
|
|
|
|
a->ac_doing = todo;
|
|
a->ac_next = alist;
|
|
alist = a;
|
|
|
|
if (ipmonopts & IPMON_VERBOSE)
|
|
print_action(a);
|
|
}
|
|
|
|
|
|
int
|
|
check_action(char *buf, char *log, int opts, int lvl)
|
|
{
|
|
ipmon_action_t *a;
|
|
struct timeval tv;
|
|
ipmon_doing_t *d;
|
|
ipmon_msg_t msg;
|
|
ipflog_t *ipf;
|
|
tcphdr_t *tcp;
|
|
iplog_t *ipl;
|
|
int matched;
|
|
u_long t1;
|
|
ip_t *ip;
|
|
|
|
matched = 0;
|
|
ipl = (iplog_t *)buf;
|
|
ipf = (ipflog_t *)(ipl +1);
|
|
ip = (ip_t *)(ipf + 1);
|
|
tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2));
|
|
|
|
msg.imm_data = ipl;
|
|
msg.imm_dsize = ipl->ipl_dsize;
|
|
msg.imm_when = ipl->ipl_time.tv_sec;
|
|
msg.imm_msg = log;
|
|
msg.imm_msglen = strlen(log);
|
|
msg.imm_loglevel = lvl;
|
|
|
|
for (a = alist; a != NULL; a = a->ac_next) {
|
|
verbose(0, "== checking config rule\n");
|
|
if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
|
|
if (a->ac_direction == IPM_IN) {
|
|
if ((ipf->fl_flags & FR_INQUE) == 0) {
|
|
verbose(8, "-- direction not in\n");
|
|
continue;
|
|
}
|
|
} else if (a->ac_direction == IPM_OUT) {
|
|
if ((ipf->fl_flags & FR_OUTQUE) == 0) {
|
|
verbose(8, "-- direction not out\n");
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) {
|
|
verbose(8, "-- type mismatch\n");
|
|
continue;
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_EVERY) != 0) {
|
|
gettimeofday(&tv, NULL);
|
|
t1 = tv.tv_sec - a->ac_lastsec;
|
|
if (tv.tv_usec <= a->ac_lastusec)
|
|
t1--;
|
|
if (a->ac_second != 0) {
|
|
if (t1 < a->ac_second) {
|
|
verbose(8, "-- too soon\n");
|
|
continue;
|
|
}
|
|
a->ac_lastsec = tv.tv_sec;
|
|
a->ac_lastusec = tv.tv_usec;
|
|
}
|
|
|
|
if (a->ac_packet != 0) {
|
|
if (a->ac_pktcnt == 0)
|
|
a->ac_pktcnt++;
|
|
else if (a->ac_pktcnt == a->ac_packet) {
|
|
a->ac_pktcnt = 0;
|
|
verbose(8, "-- packet count\n");
|
|
continue;
|
|
} else {
|
|
a->ac_pktcnt++;
|
|
verbose(8, "-- packet count\n");
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
|
|
if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) {
|
|
verbose(8, "-- dstip wrong\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
|
|
if (ip->ip_p != IPPROTO_UDP &&
|
|
ip->ip_p != IPPROTO_TCP) {
|
|
verbose(8, "-- not port protocol\n");
|
|
continue;
|
|
}
|
|
if (tcp->th_dport != a->ac_dport) {
|
|
verbose(8, "-- dport mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_GROUP) != 0) {
|
|
if (strncmp(a->ac_group, ipf->fl_group,
|
|
FR_GROUPLEN) != 0) {
|
|
verbose(8, "-- group mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
|
|
if (strcmp(a->ac_iface, ipf->fl_ifname)) {
|
|
verbose(8, "-- ifname mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
|
|
if (a->ac_proto != ip->ip_p) {
|
|
verbose(8, "-- protocol mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_RESULT) != 0) {
|
|
if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) {
|
|
if (a->ac_result != IPMR_NOMATCH) {
|
|
verbose(8, "-- ff-flags mismatch\n");
|
|
continue;
|
|
}
|
|
} else if (FR_ISPASS(ipf->fl_flags)) {
|
|
if (a->ac_result != IPMR_PASS) {
|
|
verbose(8, "-- pass mismatch\n");
|
|
continue;
|
|
}
|
|
} else if (FR_ISBLOCK(ipf->fl_flags)) {
|
|
if (a->ac_result != IPMR_BLOCK) {
|
|
verbose(8, "-- block mismatch\n");
|
|
continue;
|
|
}
|
|
} else { /* Log only */
|
|
if (a->ac_result != IPMR_LOG) {
|
|
verbose(8, "-- log mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_RULE) != 0) {
|
|
if (a->ac_rule != ipf->fl_rule) {
|
|
verbose(8, "-- rule mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
|
|
if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) {
|
|
verbose(8, "-- srcip mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
|
|
if (ip->ip_p != IPPROTO_UDP &&
|
|
ip->ip_p != IPPROTO_TCP) {
|
|
verbose(8, "-- port protocol mismatch\n");
|
|
continue;
|
|
}
|
|
if (tcp->th_sport != a->ac_sport) {
|
|
verbose(8, "-- sport mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
|
|
if (a->ac_logtag != ipf->fl_logtag) {
|
|
verbose(8, "-- logtag %d != %d\n",
|
|
a->ac_logtag, ipf->fl_logtag);
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
|
|
if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag,
|
|
IPFTAG_LEN) != 0) {
|
|
verbose(8, "-- nattag mismatch\n");
|
|
continue;
|
|
}
|
|
}
|
|
|
|
matched = 1;
|
|
verbose(8, "++ matched\n");
|
|
|
|
/*
|
|
* It matched so now perform the saves
|
|
*/
|
|
for (d = a->ac_doing; d != NULL; d = d->ipmd_next)
|
|
(*d->ipmd_store)(d->ipmd_token, &msg);
|
|
}
|
|
|
|
return(matched);
|
|
}
|
|
|
|
|
|
static void
|
|
free_action(ipmon_action_t *a)
|
|
{
|
|
ipmon_doing_t *d;
|
|
|
|
while ((d = a->ac_doing) != NULL) {
|
|
a->ac_doing = d->ipmd_next;
|
|
(*d->ipmd_saver->ims_destroy)(d->ipmd_token);
|
|
free(d);
|
|
}
|
|
|
|
if (a->ac_iface != NULL) {
|
|
free(a->ac_iface);
|
|
a->ac_iface = NULL;
|
|
}
|
|
a->ac_next = NULL;
|
|
free(a);
|
|
}
|
|
|
|
|
|
int
|
|
load_config(char *file)
|
|
{
|
|
FILE *fp;
|
|
char *s;
|
|
|
|
unload_config();
|
|
|
|
s = getenv("YYDEBUG");
|
|
if (s != NULL)
|
|
yydebug = atoi(s);
|
|
else
|
|
yydebug = 0;
|
|
|
|
yylineNum = 1;
|
|
|
|
(void) yysettab(yywords);
|
|
|
|
fp = fopen(file, "r");
|
|
if (!fp) {
|
|
perror("load_config:fopen:");
|
|
return(-1);
|
|
}
|
|
yyin = fp;
|
|
while (!feof(fp))
|
|
yyparse();
|
|
fclose(fp);
|
|
return(0);
|
|
}
|
|
|
|
|
|
void
|
|
unload_config(void)
|
|
{
|
|
ipmon_saver_int_t *sav, **imsip;
|
|
ipmon_saver_t *is;
|
|
ipmon_action_t *a;
|
|
|
|
while ((a = alist) != NULL) {
|
|
alist = a->ac_next;
|
|
free_action(a);
|
|
}
|
|
|
|
/*
|
|
* Look for savers that have been added in dynamically from the
|
|
* configuration file.
|
|
*/
|
|
for (imsip = &saverlist; (sav = *imsip) != NULL; ) {
|
|
if (sav->imsi_handle == NULL)
|
|
imsip = &sav->imsi_next;
|
|
else {
|
|
dlclose(sav->imsi_handle);
|
|
|
|
*imsip = sav->imsi_next;
|
|
is = sav->imsi_stor;
|
|
free(sav);
|
|
|
|
free(is->ims_name);
|
|
free(is);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
dump_config(void)
|
|
{
|
|
ipmon_action_t *a;
|
|
|
|
for (a = alist; a != NULL; a = a->ac_next) {
|
|
print_action(a);
|
|
|
|
printf("#\n");
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
print_action(ipmon_action_t *a)
|
|
{
|
|
ipmon_doing_t *d;
|
|
|
|
printf("match { ");
|
|
print_match(a);
|
|
printf("; }\n");
|
|
printf("do {");
|
|
for (d = a->ac_doing; d != NULL; d = d->ipmd_next) {
|
|
printf("%s", d->ipmd_saver->ims_name);
|
|
if (d->ipmd_saver->ims_print != NULL) {
|
|
printf("(\"");
|
|
(*d->ipmd_saver->ims_print)(d->ipmd_token);
|
|
printf("\")");
|
|
}
|
|
printf(";");
|
|
}
|
|
printf("};\n");
|
|
}
|
|
|
|
|
|
void *
|
|
add_doing(ipmon_saver_t *saver)
|
|
{
|
|
ipmon_saver_int_t *it;
|
|
|
|
if (find_doing(saver->ims_name) == IPM_DOING)
|
|
return(NULL);
|
|
|
|
it = calloc(1, sizeof(*it));
|
|
if (it == NULL)
|
|
return(NULL);
|
|
it->imsi_stor = saver;
|
|
it->imsi_next = saverlist;
|
|
saverlist = it;
|
|
return(it);
|
|
}
|
|
|
|
|
|
static int
|
|
find_doing(char *string)
|
|
{
|
|
ipmon_saver_int_t *it;
|
|
|
|
for (it = saverlist; it != NULL; it = it->imsi_next) {
|
|
if (!strcmp(it->imsi_stor->ims_name, string))
|
|
return(IPM_DOING);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
|
|
static ipmon_doing_t *
|
|
build_doing(char *target, char *options)
|
|
{
|
|
ipmon_saver_int_t *it;
|
|
char *strarray[2];
|
|
ipmon_doing_t *d, *d1;
|
|
ipmon_action_t *a;
|
|
ipmon_saver_t *save;
|
|
|
|
d = calloc(1, sizeof(*d));
|
|
if (d == NULL)
|
|
return(NULL);
|
|
|
|
for (it = saverlist; it != NULL; it = it->imsi_next) {
|
|
if (!strcmp(it->imsi_stor->ims_name, target))
|
|
break;
|
|
}
|
|
if (it == NULL) {
|
|
free(d);
|
|
return(NULL);
|
|
}
|
|
|
|
strarray[0] = options;
|
|
strarray[1] = NULL;
|
|
|
|
d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray);
|
|
if (d->ipmd_token == NULL) {
|
|
free(d);
|
|
return(NULL);
|
|
}
|
|
|
|
save = it->imsi_stor;
|
|
d->ipmd_saver = save;
|
|
d->ipmd_store = it->imsi_stor->ims_store;
|
|
|
|
/*
|
|
* Look for duplicate do-things that need to be dup'd
|
|
*/
|
|
for (a = alist; a != NULL; a = a->ac_next) {
|
|
for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) {
|
|
if (save != d1->ipmd_saver)
|
|
continue;
|
|
if (save->ims_match == NULL || save->ims_dup == NULL)
|
|
continue;
|
|
if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token))
|
|
continue;
|
|
|
|
(*d->ipmd_saver->ims_destroy)(d->ipmd_token);
|
|
d->ipmd_token = (*save->ims_dup)(d1->ipmd_token);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return(d);
|
|
}
|
|
|
|
|
|
static void
|
|
print_match(ipmon_action_t *a)
|
|
{
|
|
char *coma = "";
|
|
|
|
if ((a->ac_mflag & IPMAC_DIRECTION) != 0) {
|
|
printf("direction = ");
|
|
if (a->ac_direction == IPM_IN)
|
|
printf("in");
|
|
else if (a->ac_direction == IPM_OUT)
|
|
printf("out");
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_DSTIP) != 0) {
|
|
printf("%sdstip = ", coma);
|
|
printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_DSTPORT) != 0) {
|
|
printf("%sdstport = %hu", coma, ntohs(a->ac_dport));
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_GROUP) != 0) {
|
|
char group[FR_GROUPLEN+1];
|
|
|
|
strncpy(group, a->ac_group, FR_GROUPLEN);
|
|
group[FR_GROUPLEN] = '\0';
|
|
printf("%sgroup = %s", coma, group);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_INTERFACE) != 0) {
|
|
printf("%siface = %s", coma, a->ac_iface);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_LOGTAG) != 0) {
|
|
printf("%slogtag = %u", coma, a->ac_logtag);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_NATTAG) != 0) {
|
|
char tag[17];
|
|
|
|
strncpy(tag, a->ac_nattag, 16);
|
|
tag[16] = '\0';
|
|
printf("%snattag = %s", coma, tag);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) {
|
|
printf("%sprotocol = %u", coma, a->ac_proto);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_RESULT) != 0) {
|
|
printf("%sresult = ", coma);
|
|
switch (a->ac_result)
|
|
{
|
|
case IPMR_LOG :
|
|
printf("log");
|
|
break;
|
|
case IPMR_PASS :
|
|
printf("pass");
|
|
break;
|
|
case IPMR_BLOCK :
|
|
printf("block");
|
|
break;
|
|
case IPMR_NOMATCH :
|
|
printf("nomatch");
|
|
break;
|
|
}
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_RULE) != 0) {
|
|
printf("%srule = %u", coma, a->ac_rule);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_EVERY) != 0) {
|
|
if (a->ac_packet > 1) {
|
|
printf("%severy %d packets", coma, a->ac_packet);
|
|
coma = ", ";
|
|
} else if (a->ac_packet == 1) {
|
|
printf("%severy packet", coma);
|
|
coma = ", ";
|
|
}
|
|
if (a->ac_second > 1) {
|
|
printf("%severy %d seconds", coma, a->ac_second);
|
|
coma = ", ";
|
|
} else if (a->ac_second == 1) {
|
|
printf("%severy second", coma);
|
|
coma = ", ";
|
|
}
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_SRCIP) != 0) {
|
|
printf("%ssrcip = ", coma);
|
|
printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk);
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_SRCPORT) != 0) {
|
|
printf("%ssrcport = %hu", coma, ntohs(a->ac_sport));
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_TYPE) != 0) {
|
|
printf("%stype = ", coma);
|
|
switch (a->ac_type)
|
|
{
|
|
case IPL_LOGIPF :
|
|
printf("ipf");
|
|
break;
|
|
case IPL_LOGSTATE :
|
|
printf("state");
|
|
break;
|
|
case IPL_LOGNAT :
|
|
printf("nat");
|
|
break;
|
|
}
|
|
coma = ", ";
|
|
}
|
|
|
|
if ((a->ac_mflag & IPMAC_WITH) != 0) {
|
|
printf("%swith ", coma);
|
|
coma = ", ";
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
install_saver(char *name, char *path)
|
|
{
|
|
ipmon_saver_int_t *isi;
|
|
ipmon_saver_t *is;
|
|
char nbuf[80];
|
|
|
|
if (find_doing(name) == IPM_DOING)
|
|
return(-1);
|
|
|
|
isi = calloc(1, sizeof(*isi));
|
|
if (isi == NULL)
|
|
return(-1);
|
|
|
|
is = calloc(1, sizeof(*is));
|
|
if (is == NULL)
|
|
goto loaderror;
|
|
|
|
is->ims_name = name;
|
|
|
|
#ifdef RTLD_LAZY
|
|
isi->imsi_handle = dlopen(path, RTLD_LAZY);
|
|
#endif
|
|
#ifdef DL_LAZY
|
|
isi->imsi_handle = dlopen(path, DL_LAZY);
|
|
#endif
|
|
|
|
if (isi->imsi_handle == NULL)
|
|
goto loaderror;
|
|
|
|
snprintf(nbuf, sizeof(nbuf), "%sdup", name);
|
|
is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf);
|
|
|
|
snprintf(nbuf, sizeof(nbuf), "%sdestroy", name);
|
|
is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf);
|
|
if (is->ims_destroy == NULL)
|
|
goto loaderror;
|
|
|
|
snprintf(nbuf, sizeof(nbuf), "%smatch", name);
|
|
is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf);
|
|
|
|
snprintf(nbuf, sizeof(nbuf), "%sparse", name);
|
|
is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf);
|
|
if (is->ims_parse == NULL)
|
|
goto loaderror;
|
|
|
|
snprintf(nbuf, sizeof(nbuf), "%sprint", name);
|
|
is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf);
|
|
if (is->ims_print == NULL)
|
|
goto loaderror;
|
|
|
|
snprintf(nbuf, sizeof(nbuf), "%sstore", name);
|
|
is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf);
|
|
if (is->ims_store == NULL)
|
|
goto loaderror;
|
|
|
|
isi->imsi_stor = is;
|
|
isi->imsi_next = saverlist;
|
|
saverlist = isi;
|
|
|
|
return(0);
|
|
|
|
loaderror:
|
|
if (isi->imsi_handle != NULL)
|
|
dlclose(isi->imsi_handle);
|
|
free(isi);
|
|
if (is != NULL)
|
|
free(is);
|
|
return(-1);
|
|
}
|