/* $NetBSD: ipmon_y.y,v 1.2 2012/10/21 22:57:48 christos Exp $ */
/*
* 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 __P((char *));
extern int yyparse __P((void));
extern int yylex __P((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 __P((opt_t *, ipmon_doing_t *));
static opt_t *new_opt __P((int));
static void free_action __P((ipmon_action_t *));
static void print_action __P((ipmon_action_t *));
static int find_doing __P((char *));
static ipmon_doing_t *build_doing __P((char *, char *));
static void print_match __P((ipmon_action_t *));
static int install_saver __P((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(type)
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(olist, todo)
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(buf, log, opts, lvl)
const char *buf, *log;
int opts, 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 = (char *)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(a)
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(file)
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()
{
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()
{
ipmon_action_t *a;
for (a = alist; a != NULL; a = a->ac_next) {
print_action(a);
printf("#\n");
}
}
static void
print_action(a)
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(saver)
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(string)
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(target, options)
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(a)
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(name, path)
char *name, *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;
}