1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3170268Sdarrenr/* 4255332Scy * Copyright (C) 2012 by Darren Reed. 5170268Sdarrenr * 6170268Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7170268Sdarrenr */ 8145510Sdarrenr%{ 9145510Sdarrenr#include "ipf.h" 10145510Sdarrenr#include <syslog.h> 11145510Sdarrenr#undef OPT_NAT 12145510Sdarrenr#undef OPT_VERBOSE 13145510Sdarrenr#include "ipmon_l.h" 14145510Sdarrenr#include "ipmon.h" 15145510Sdarrenr 16255332Scy#include <dlfcn.h> 17255332Scy 18145510Sdarrenr#define YYDEBUG 1 19145510Sdarrenr 20145510Sdarrenrextern void yyerror __P((char *)); 21145510Sdarrenrextern int yyparse __P((void)); 22145510Sdarrenrextern int yylex __P((void)); 23145510Sdarrenrextern int yydebug; 24145510Sdarrenrextern FILE *yyin; 25145510Sdarrenrextern int yylineNum; 26255332Scyextern int ipmonopts; 27145510Sdarrenr 28255332Scytypedef struct opt_s { 29255332Scy struct opt_s *o_next; 30145510Sdarrenr int o_line; 31145510Sdarrenr int o_type; 32145510Sdarrenr int o_num; 33145510Sdarrenr char *o_str; 34145510Sdarrenr struct in_addr o_ip; 35255332Scy int o_logfac; 36255332Scy int o_logpri; 37145510Sdarrenr} opt_t; 38145510Sdarrenr 39255332Scystatic void build_action __P((opt_t *, ipmon_doing_t *)); 40145510Sdarrenrstatic opt_t *new_opt __P((int)); 41145510Sdarrenrstatic void free_action __P((ipmon_action_t *)); 42255332Scystatic void print_action __P((ipmon_action_t *)); 43255332Scystatic int find_doing __P((char *)); 44255332Scystatic ipmon_doing_t *build_doing __P((char *, char *)); 45255332Scystatic void print_match __P((ipmon_action_t *)); 46255332Scystatic int install_saver __P((char *, char *)); 47145510Sdarrenr 48145510Sdarrenrstatic ipmon_action_t *alist = NULL; 49255332Scy 50255332Scyipmon_saver_int_t *saverlist = NULL; 51145510Sdarrenr%} 52145510Sdarrenr 53145510Sdarrenr%union { 54145510Sdarrenr char *str; 55145510Sdarrenr u_32_t num; 56145510Sdarrenr struct in_addr addr; 57255332Scy struct opt_s *opt; 58145510Sdarrenr union i6addr ip6; 59255332Scy struct ipmon_doing_s *ipmd; 60145510Sdarrenr} 61145510Sdarrenr 62145510Sdarrenr%token <num> YY_NUMBER YY_HEX 63145510Sdarrenr%token <str> YY_STR 64145510Sdarrenr%token <ip6> YY_IPV6 65255332Scy%token YY_COMMENT 66145510Sdarrenr%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 67145510Sdarrenr%token YY_RANGE_OUT YY_RANGE_IN 68145510Sdarrenr 69145510Sdarrenr%token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT 70255332Scy%token IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION 71145510Sdarrenr%token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE 72145510Sdarrenr%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH 73255332Scy%token IPM_DO IPM_DOING IPM_TYPE IPM_NAT 74145510Sdarrenr%token IPM_STATE IPM_NATTAG IPM_IPF 75145510Sdarrenr%type <addr> ipv4 76255332Scy%type <opt> direction dstip dstport every group interface 77145510Sdarrenr%type <opt> protocol result rule srcip srcport logtag matching 78255332Scy%type <opt> matchopt nattag type 79255332Scy%type <num> typeopt 80255332Scy%type <ipmd> doopt doing 81145510Sdarrenr 82145510Sdarrenr%% 83255332Scyfile: action 84255332Scy | file action 85145510Sdarrenr ; 86145510Sdarrenr 87255332Scyaction: line ';' 88255332Scy | assign ';' 89145510Sdarrenr | IPM_COMMENT 90145510Sdarrenr | YY_COMMENT 91145510Sdarrenr ; 92145510Sdarrenr 93255332Scyline: IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}' 94255332Scy { build_action($3, $8); 95145510Sdarrenr resetlexer(); 96255332Scy } 97255332Scy | IPM_LOADACTION YY_STR YY_STR { if (install_saver($2, $3)) 98255332Scy yyerror("install saver"); 99255332Scy } 100255332Scy ; 101255332Scy 102255332Scyassign: YY_STR assigning YY_STR { set_variable($1, $3); 103255332Scy resetlexer(); 104145510Sdarrenr free($1); 105145510Sdarrenr free($3); 106170268Sdarrenr yyvarnext = 0; 107255332Scy } 108145510Sdarrenr ; 109145510Sdarrenr 110145510Sdarrenrassigning: 111145510Sdarrenr '=' { yyvarnext = 1; } 112145510Sdarrenr ; 113145510Sdarrenr 114145510Sdarrenrmatching: 115145510Sdarrenr matchopt { $$ = $1; } 116145510Sdarrenr | matchopt ',' matching { $1->o_next = $3; $$ = $1; } 117145510Sdarrenr ; 118145510Sdarrenr 119145510Sdarrenrmatchopt: 120145510Sdarrenr direction { $$ = $1; } 121145510Sdarrenr | dstip { $$ = $1; } 122145510Sdarrenr | dstport { $$ = $1; } 123145510Sdarrenr | every { $$ = $1; } 124145510Sdarrenr | group { $$ = $1; } 125145510Sdarrenr | interface { $$ = $1; } 126145510Sdarrenr | protocol { $$ = $1; } 127145510Sdarrenr | result { $$ = $1; } 128145510Sdarrenr | rule { $$ = $1; } 129145510Sdarrenr | srcip { $$ = $1; } 130145510Sdarrenr | srcport { $$ = $1; } 131145510Sdarrenr | logtag { $$ = $1; } 132145510Sdarrenr | nattag { $$ = $1; } 133145510Sdarrenr | type { $$ = $1; } 134145510Sdarrenr ; 135145510Sdarrenr 136145510Sdarrenrdoing: 137145510Sdarrenr doopt { $$ = $1; } 138255332Scy | doopt ',' doing { $1->ipmd_next = $3; $$ = $1; } 139145510Sdarrenr ; 140145510Sdarrenr 141145510Sdarrenrdoopt: 142255332Scy YY_STR { if (find_doing($1) != IPM_DOING) 143255332Scy yyerror("unknown action"); 144255332Scy } 145255332Scy '(' YY_STR ')' { $$ = build_doing($1, $4); 146255332Scy if ($$ == NULL) 147255332Scy yyerror("action building"); 148255332Scy } 149255332Scy | YY_STR { if (find_doing($1) == IPM_DOING) 150255332Scy $$ = build_doing($1, NULL); 151255332Scy } 152145510Sdarrenr ; 153145510Sdarrenr 154145510Sdarrenrdirection: 155145510Sdarrenr IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION); 156145510Sdarrenr $$->o_num = IPM_IN; } 157145510Sdarrenr | IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION); 158145510Sdarrenr $$->o_num = IPM_OUT; } 159145510Sdarrenr ; 160145510Sdarrenr 161145510Sdarrenrdstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP); 162145510Sdarrenr $$->o_ip = $3; 163145510Sdarrenr $$->o_num = $5; } 164145510Sdarrenr ; 165145510Sdarrenr 166145510Sdarrenrdstport: 167145510Sdarrenr IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT); 168145510Sdarrenr $$->o_num = $3; } 169145510Sdarrenr | IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT); 170145510Sdarrenr $$->o_str = $3; } 171145510Sdarrenr ; 172145510Sdarrenr 173145510Sdarrenrevery: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND); 174145510Sdarrenr $$->o_num = 1; } 175145510Sdarrenr | IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND); 176145510Sdarrenr $$->o_num = $2; } 177145510Sdarrenr | IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET); 178145510Sdarrenr $$->o_num = 1; } 179145510Sdarrenr | IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET); 180145510Sdarrenr $$->o_num = $2; } 181145510Sdarrenr ; 182145510Sdarrenr 183145510Sdarrenrgroup: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP); 184145510Sdarrenr $$->o_num = $3; } 185145510Sdarrenr | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP); 186145510Sdarrenr $$->o_str = $3; } 187145510Sdarrenr ; 188145510Sdarrenr 189145510Sdarrenrinterface: 190145510Sdarrenr IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE); 191145510Sdarrenr $$->o_str = $3; } 192145510Sdarrenr ; 193145510Sdarrenr 194145510Sdarrenrlogtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG); 195145510Sdarrenr $$->o_num = $3; } 196145510Sdarrenr ; 197145510Sdarrenr 198145510Sdarrenrnattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG); 199145510Sdarrenr $$->o_str = $3; } 200145510Sdarrenr ; 201145510Sdarrenr 202145510Sdarrenrprotocol: 203145510Sdarrenr IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL); 204145510Sdarrenr $$->o_num = $3; } 205145510Sdarrenr | IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL); 206145510Sdarrenr $$->o_num = getproto($3); 207145510Sdarrenr free($3); 208145510Sdarrenr } 209145510Sdarrenr ; 210145510Sdarrenr 211145510Sdarrenrresult: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT); 212145510Sdarrenr $$->o_str = $3; } 213145510Sdarrenr ; 214145510Sdarrenr 215145510Sdarrenrrule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE); 216145510Sdarrenr $$->o_num = YY_NUMBER; } 217145510Sdarrenr ; 218145510Sdarrenr 219145510Sdarrenrsrcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP); 220145510Sdarrenr $$->o_ip = $3; 221145510Sdarrenr $$->o_num = $5; } 222145510Sdarrenr ; 223145510Sdarrenr 224145510Sdarrenrsrcport: 225145510Sdarrenr IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT); 226145510Sdarrenr $$->o_num = $3; } 227145510Sdarrenr | IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT); 228145510Sdarrenr $$->o_str = $3; } 229145510Sdarrenr ; 230145510Sdarrenr 231145510Sdarrenrtype: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE); 232145510Sdarrenr $$->o_num = $3; } 233145510Sdarrenr ; 234145510Sdarrenr 235145510Sdarrenrtypeopt: 236145510Sdarrenr IPM_IPF { $$ = IPL_MAGIC; } 237145510Sdarrenr | IPM_NAT { $$ = IPL_MAGIC_NAT; } 238145510Sdarrenr | IPM_STATE { $$ = IPL_MAGIC_STATE; } 239145510Sdarrenr ; 240145510Sdarrenr 241145510Sdarrenr 242145510Sdarrenr 243145510Sdarrenripv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 244145510Sdarrenr { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 245145510Sdarrenr yyerror("Invalid octet string for IP address"); 246145510Sdarrenr return 0; 247145510Sdarrenr } 248145510Sdarrenr $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 249145510Sdarrenr $$.s_addr = htonl($$.s_addr); 250145510Sdarrenr } 251145510Sdarrenr%% 252145510Sdarrenrstatic struct wordtab yywords[] = { 253145510Sdarrenr { "body", IPM_BODY }, 254145510Sdarrenr { "direction", IPM_DIRECTION }, 255145510Sdarrenr { "do", IPM_DO }, 256145510Sdarrenr { "dstip", IPM_DSTIP }, 257145510Sdarrenr { "dstport", IPM_DSTPORT }, 258145510Sdarrenr { "every", IPM_EVERY }, 259145510Sdarrenr { "group", IPM_GROUP }, 260145510Sdarrenr { "in", IPM_IN }, 261145510Sdarrenr { "interface", IPM_INTERFACE }, 262145510Sdarrenr { "ipf", IPM_IPF }, 263255332Scy { "load_action",IPM_LOADACTION }, 264145510Sdarrenr { "logtag", IPM_LOGTAG }, 265145510Sdarrenr { "match", IPM_MATCH }, 266145510Sdarrenr { "nat", IPM_NAT }, 267145510Sdarrenr { "nattag", IPM_NATTAG }, 268145510Sdarrenr { "no", IPM_NO }, 269145510Sdarrenr { "out", IPM_OUT }, 270145510Sdarrenr { "packet", IPM_PACKET }, 271145510Sdarrenr { "packets", IPM_PACKETS }, 272145510Sdarrenr { "protocol", IPM_PROTOCOL }, 273145510Sdarrenr { "result", IPM_RESULT }, 274145510Sdarrenr { "rule", IPM_RULE }, 275145510Sdarrenr { "second", IPM_SECOND }, 276145510Sdarrenr { "seconds", IPM_SECONDS }, 277145510Sdarrenr { "srcip", IPM_SRCIP }, 278145510Sdarrenr { "srcport", IPM_SRCPORT }, 279145510Sdarrenr { "state", IPM_STATE }, 280145510Sdarrenr { "with", IPM_WITH }, 281145510Sdarrenr { NULL, 0 } 282145510Sdarrenr}; 283145510Sdarrenr 284145510Sdarrenrstatic int macflags[17][2] = { 285145510Sdarrenr { IPM_DIRECTION, IPMAC_DIRECTION }, 286145510Sdarrenr { IPM_DSTIP, IPMAC_DSTIP }, 287145510Sdarrenr { IPM_DSTPORT, IPMAC_DSTPORT }, 288145510Sdarrenr { IPM_GROUP, IPMAC_GROUP }, 289145510Sdarrenr { IPM_INTERFACE, IPMAC_INTERFACE }, 290145510Sdarrenr { IPM_LOGTAG, IPMAC_LOGTAG }, 291145510Sdarrenr { IPM_NATTAG, IPMAC_NATTAG }, 292145510Sdarrenr { IPM_PACKET, IPMAC_EVERY }, 293145510Sdarrenr { IPM_PROTOCOL, IPMAC_PROTOCOL }, 294145510Sdarrenr { IPM_RESULT, IPMAC_RESULT }, 295145510Sdarrenr { IPM_RULE, IPMAC_RULE }, 296145510Sdarrenr { IPM_SECOND, IPMAC_EVERY }, 297145510Sdarrenr { IPM_SRCIP, IPMAC_SRCIP }, 298145510Sdarrenr { IPM_SRCPORT, IPMAC_SRCPORT }, 299145510Sdarrenr { IPM_TYPE, IPMAC_TYPE }, 300145510Sdarrenr { IPM_WITH, IPMAC_WITH }, 301145510Sdarrenr { 0, 0 } 302145510Sdarrenr}; 303145510Sdarrenr 304255332Scystatic opt_t * 305255332Scynew_opt(type) 306255332Scy int type; 307145510Sdarrenr{ 308145510Sdarrenr opt_t *o; 309145510Sdarrenr 310255332Scy o = (opt_t *)calloc(1, sizeof(*o)); 311145510Sdarrenr o->o_type = type; 312145510Sdarrenr o->o_line = yylineNum; 313255332Scy o->o_logfac = -1; 314255332Scy o->o_logpri = -1; 315145510Sdarrenr return o; 316145510Sdarrenr} 317145510Sdarrenr 318255332Scystatic void 319255332Scybuild_action(olist, todo) 320255332Scy opt_t *olist; 321255332Scy ipmon_doing_t *todo; 322145510Sdarrenr{ 323145510Sdarrenr ipmon_action_t *a; 324145510Sdarrenr opt_t *o; 325145510Sdarrenr int i; 326145510Sdarrenr 327145510Sdarrenr a = (ipmon_action_t *)calloc(1, sizeof(*a)); 328145510Sdarrenr if (a == NULL) 329145510Sdarrenr return; 330255332Scy 331145510Sdarrenr while ((o = olist) != NULL) { 332145510Sdarrenr /* 333145510Sdarrenr * Check to see if the same comparator is being used more than 334145510Sdarrenr * once per matching statement. 335145510Sdarrenr */ 336145510Sdarrenr for (i = 0; macflags[i][0]; i++) 337145510Sdarrenr if (macflags[i][0] == o->o_type) 338145510Sdarrenr break; 339145510Sdarrenr if (macflags[i][1] & a->ac_mflag) { 340145510Sdarrenr fprintf(stderr, "%s redfined on line %d\n", 341145510Sdarrenr yykeytostr(o->o_type), yylineNum); 342145510Sdarrenr if (o->o_str != NULL) 343145510Sdarrenr free(o->o_str); 344145510Sdarrenr olist = o->o_next; 345145510Sdarrenr free(o); 346145510Sdarrenr continue; 347145510Sdarrenr } 348145510Sdarrenr 349145510Sdarrenr a->ac_mflag |= macflags[i][1]; 350145510Sdarrenr 351145510Sdarrenr switch (o->o_type) 352145510Sdarrenr { 353145510Sdarrenr case IPM_DIRECTION : 354145510Sdarrenr a->ac_direction = o->o_num; 355145510Sdarrenr break; 356145510Sdarrenr case IPM_DSTIP : 357145510Sdarrenr a->ac_dip = o->o_ip.s_addr; 358145510Sdarrenr a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num)); 359145510Sdarrenr break; 360145510Sdarrenr case IPM_DSTPORT : 361145510Sdarrenr a->ac_dport = htons(o->o_num); 362145510Sdarrenr break; 363145510Sdarrenr case IPM_INTERFACE : 364145510Sdarrenr a->ac_iface = o->o_str; 365145510Sdarrenr o->o_str = NULL; 366145510Sdarrenr break; 367255332Scy case IPM_GROUP : 368145510Sdarrenr if (o->o_str != NULL) 369145510Sdarrenr strncpy(a->ac_group, o->o_str, FR_GROUPLEN); 370145510Sdarrenr else 371145510Sdarrenr sprintf(a->ac_group, "%d", o->o_num); 372145510Sdarrenr break; 373145510Sdarrenr case IPM_LOGTAG : 374145510Sdarrenr a->ac_logtag = o->o_num; 375145510Sdarrenr break; 376145510Sdarrenr case IPM_NATTAG : 377145510Sdarrenr strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag)); 378145510Sdarrenr break; 379145510Sdarrenr case IPM_PACKET : 380145510Sdarrenr a->ac_packet = o->o_num; 381145510Sdarrenr break; 382145510Sdarrenr case IPM_PROTOCOL : 383145510Sdarrenr a->ac_proto = o->o_num; 384145510Sdarrenr break; 385145510Sdarrenr case IPM_RULE : 386145510Sdarrenr a->ac_rule = o->o_num; 387145510Sdarrenr break; 388145510Sdarrenr case IPM_RESULT : 389145510Sdarrenr if (!strcasecmp(o->o_str, "pass")) 390145510Sdarrenr a->ac_result = IPMR_PASS; 391145510Sdarrenr else if (!strcasecmp(o->o_str, "block")) 392145510Sdarrenr a->ac_result = IPMR_BLOCK; 393145510Sdarrenr else if (!strcasecmp(o->o_str, "nomatch")) 394145510Sdarrenr a->ac_result = IPMR_NOMATCH; 395145510Sdarrenr else if (!strcasecmp(o->o_str, "log")) 396145510Sdarrenr a->ac_result = IPMR_LOG; 397145510Sdarrenr break; 398145510Sdarrenr case IPM_SECOND : 399145510Sdarrenr a->ac_second = o->o_num; 400145510Sdarrenr break; 401145510Sdarrenr case IPM_SRCIP : 402145510Sdarrenr a->ac_sip = o->o_ip.s_addr; 403145510Sdarrenr a->ac_smsk = htonl(0xffffffff << (32 - o->o_num)); 404145510Sdarrenr break; 405145510Sdarrenr case IPM_SRCPORT : 406145510Sdarrenr a->ac_sport = htons(o->o_num); 407145510Sdarrenr break; 408145510Sdarrenr case IPM_TYPE : 409145510Sdarrenr a->ac_type = o->o_num; 410145510Sdarrenr break; 411145510Sdarrenr case IPM_WITH : 412145510Sdarrenr break; 413145510Sdarrenr default : 414145510Sdarrenr break; 415145510Sdarrenr } 416145510Sdarrenr 417145510Sdarrenr olist = o->o_next; 418145510Sdarrenr if (o->o_str != NULL) 419145510Sdarrenr free(o->o_str); 420145510Sdarrenr free(o); 421145510Sdarrenr } 422255332Scy 423255332Scy a->ac_doing = todo; 424145510Sdarrenr a->ac_next = alist; 425145510Sdarrenr alist = a; 426255332Scy 427255332Scy if (ipmonopts & IPMON_VERBOSE) 428255332Scy print_action(a); 429145510Sdarrenr} 430145510Sdarrenr 431145510Sdarrenr 432255332Scyint 433255332Scycheck_action(buf, log, opts, lvl) 434255332Scy char *buf, *log; 435255332Scy int opts, lvl; 436145510Sdarrenr{ 437145510Sdarrenr ipmon_action_t *a; 438145510Sdarrenr struct timeval tv; 439255332Scy ipmon_doing_t *d; 440255332Scy ipmon_msg_t msg; 441145510Sdarrenr ipflog_t *ipf; 442145510Sdarrenr tcphdr_t *tcp; 443145510Sdarrenr iplog_t *ipl; 444145510Sdarrenr int matched; 445145510Sdarrenr u_long t1; 446145510Sdarrenr ip_t *ip; 447145510Sdarrenr 448145510Sdarrenr matched = 0; 449145510Sdarrenr ipl = (iplog_t *)buf; 450145510Sdarrenr ipf = (ipflog_t *)(ipl +1); 451145510Sdarrenr ip = (ip_t *)(ipf + 1); 452145510Sdarrenr tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); 453145510Sdarrenr 454255332Scy msg.imm_data = ipl; 455255332Scy msg.imm_dsize = ipl->ipl_dsize; 456255332Scy msg.imm_when = ipl->ipl_time.tv_sec; 457255332Scy msg.imm_msg = log; 458255332Scy msg.imm_msglen = strlen(log); 459255332Scy msg.imm_loglevel = lvl; 460255332Scy 461145510Sdarrenr for (a = alist; a != NULL; a = a->ac_next) { 462255332Scy verbose(0, "== checking config rule\n"); 463145510Sdarrenr if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { 464145510Sdarrenr if (a->ac_direction == IPM_IN) { 465255332Scy if ((ipf->fl_flags & FR_INQUE) == 0) { 466255332Scy verbose(8, "-- direction not in\n"); 467145510Sdarrenr continue; 468255332Scy } 469145510Sdarrenr } else if (a->ac_direction == IPM_OUT) { 470255332Scy if ((ipf->fl_flags & FR_OUTQUE) == 0) { 471255332Scy verbose(8, "-- direction not out\n"); 472145510Sdarrenr continue; 473255332Scy } 474145510Sdarrenr } 475145510Sdarrenr } 476145510Sdarrenr 477255332Scy if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) { 478255332Scy verbose(8, "-- type mismatch\n"); 479145510Sdarrenr continue; 480255332Scy } 481145510Sdarrenr 482145510Sdarrenr if ((a->ac_mflag & IPMAC_EVERY) != 0) { 483145510Sdarrenr gettimeofday(&tv, NULL); 484145510Sdarrenr t1 = tv.tv_sec - a->ac_lastsec; 485145510Sdarrenr if (tv.tv_usec <= a->ac_lastusec) 486145510Sdarrenr t1--; 487145510Sdarrenr if (a->ac_second != 0) { 488255332Scy if (t1 < a->ac_second) { 489255332Scy verbose(8, "-- too soon\n"); 490145510Sdarrenr continue; 491255332Scy } 492145510Sdarrenr a->ac_lastsec = tv.tv_sec; 493145510Sdarrenr a->ac_lastusec = tv.tv_usec; 494145510Sdarrenr } 495145510Sdarrenr 496145510Sdarrenr if (a->ac_packet != 0) { 497145510Sdarrenr if (a->ac_pktcnt == 0) 498145510Sdarrenr a->ac_pktcnt++; 499145510Sdarrenr else if (a->ac_pktcnt == a->ac_packet) { 500145510Sdarrenr a->ac_pktcnt = 0; 501255332Scy verbose(8, "-- packet count\n"); 502145510Sdarrenr continue; 503145510Sdarrenr } else { 504145510Sdarrenr a->ac_pktcnt++; 505255332Scy verbose(8, "-- packet count\n"); 506145510Sdarrenr continue; 507145510Sdarrenr } 508145510Sdarrenr } 509145510Sdarrenr } 510145510Sdarrenr 511145510Sdarrenr if ((a->ac_mflag & IPMAC_DSTIP) != 0) { 512255332Scy if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) { 513255332Scy verbose(8, "-- dstip wrong\n"); 514145510Sdarrenr continue; 515255332Scy } 516145510Sdarrenr } 517145510Sdarrenr 518145510Sdarrenr if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 519255332Scy if (ip->ip_p != IPPROTO_UDP && 520255332Scy ip->ip_p != IPPROTO_TCP) { 521255332Scy verbose(8, "-- not port protocol\n"); 522145510Sdarrenr continue; 523255332Scy } 524255332Scy if (tcp->th_dport != a->ac_dport) { 525255332Scy verbose(8, "-- dport mismatch\n"); 526145510Sdarrenr continue; 527255332Scy } 528145510Sdarrenr } 529145510Sdarrenr 530145510Sdarrenr if ((a->ac_mflag & IPMAC_GROUP) != 0) { 531145510Sdarrenr if (strncmp(a->ac_group, ipf->fl_group, 532255332Scy FR_GROUPLEN) != 0) { 533255332Scy verbose(8, "-- group mismatch\n"); 534145510Sdarrenr continue; 535255332Scy } 536145510Sdarrenr } 537145510Sdarrenr 538145510Sdarrenr if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 539255332Scy if (strcmp(a->ac_iface, ipf->fl_ifname)) { 540255332Scy verbose(8, "-- ifname mismatch\n"); 541145510Sdarrenr continue; 542255332Scy } 543145510Sdarrenr } 544145510Sdarrenr 545145510Sdarrenr if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { 546255332Scy if (a->ac_proto != ip->ip_p) { 547255332Scy verbose(8, "-- protocol mismatch\n"); 548145510Sdarrenr continue; 549255332Scy } 550145510Sdarrenr } 551145510Sdarrenr 552145510Sdarrenr if ((a->ac_mflag & IPMAC_RESULT) != 0) { 553145510Sdarrenr if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) { 554255332Scy if (a->ac_result != IPMR_NOMATCH) { 555255332Scy verbose(8, "-- ff-flags mismatch\n"); 556145510Sdarrenr continue; 557255332Scy } 558145510Sdarrenr } else if (FR_ISPASS(ipf->fl_flags)) { 559255332Scy if (a->ac_result != IPMR_PASS) { 560255332Scy verbose(8, "-- pass mismatch\n"); 561145510Sdarrenr continue; 562255332Scy } 563145510Sdarrenr } else if (FR_ISBLOCK(ipf->fl_flags)) { 564255332Scy if (a->ac_result != IPMR_BLOCK) { 565255332Scy verbose(8, "-- block mismatch\n"); 566145510Sdarrenr continue; 567255332Scy } 568145510Sdarrenr } else { /* Log only */ 569255332Scy if (a->ac_result != IPMR_LOG) { 570255332Scy verbose(8, "-- log mismatch\n"); 571145510Sdarrenr continue; 572255332Scy } 573145510Sdarrenr } 574145510Sdarrenr } 575145510Sdarrenr 576145510Sdarrenr if ((a->ac_mflag & IPMAC_RULE) != 0) { 577255332Scy if (a->ac_rule != ipf->fl_rule) { 578255332Scy verbose(8, "-- rule mismatch\n"); 579145510Sdarrenr continue; 580255332Scy } 581145510Sdarrenr } 582145510Sdarrenr 583145510Sdarrenr if ((a->ac_mflag & IPMAC_SRCIP) != 0) { 584255332Scy if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) { 585255332Scy verbose(8, "-- srcip mismatch\n"); 586145510Sdarrenr continue; 587255332Scy } 588145510Sdarrenr } 589145510Sdarrenr 590145510Sdarrenr if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 591255332Scy if (ip->ip_p != IPPROTO_UDP && 592255332Scy ip->ip_p != IPPROTO_TCP) { 593255332Scy verbose(8, "-- port protocol mismatch\n"); 594145510Sdarrenr continue; 595255332Scy } 596255332Scy if (tcp->th_sport != a->ac_sport) { 597255332Scy verbose(8, "-- sport mismatch\n"); 598145510Sdarrenr continue; 599255332Scy } 600145510Sdarrenr } 601145510Sdarrenr 602145510Sdarrenr if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 603255332Scy if (a->ac_logtag != ipf->fl_logtag) { 604255332Scy verbose(8, "-- logtag %d != %d\n", 605255332Scy a->ac_logtag, ipf->fl_logtag); 606145510Sdarrenr continue; 607255332Scy } 608145510Sdarrenr } 609145510Sdarrenr 610145510Sdarrenr if ((a->ac_mflag & IPMAC_NATTAG) != 0) { 611145510Sdarrenr if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag, 612255332Scy IPFTAG_LEN) != 0) { 613255332Scy verbose(8, "-- nattag mismatch\n"); 614145510Sdarrenr continue; 615255332Scy } 616145510Sdarrenr } 617145510Sdarrenr 618145510Sdarrenr matched = 1; 619255332Scy verbose(8, "++ matched\n"); 620145510Sdarrenr 621145510Sdarrenr /* 622255332Scy * It matched so now perform the saves 623145510Sdarrenr */ 624255332Scy for (d = a->ac_doing; d != NULL; d = d->ipmd_next) 625255332Scy (*d->ipmd_store)(d->ipmd_token, &msg); 626145510Sdarrenr } 627145510Sdarrenr 628145510Sdarrenr return matched; 629145510Sdarrenr} 630145510Sdarrenr 631145510Sdarrenr 632255332Scystatic void 633255332Scyfree_action(a) 634255332Scy ipmon_action_t *a; 635145510Sdarrenr{ 636255332Scy ipmon_doing_t *d; 637255332Scy 638255332Scy while ((d = a->ac_doing) != NULL) { 639255332Scy a->ac_doing = d->ipmd_next; 640255332Scy (*d->ipmd_saver->ims_destroy)(d->ipmd_token); 641255332Scy free(d); 642145510Sdarrenr } 643255332Scy 644145510Sdarrenr if (a->ac_iface != NULL) { 645145510Sdarrenr free(a->ac_iface); 646145510Sdarrenr a->ac_iface = NULL; 647145510Sdarrenr } 648145510Sdarrenr a->ac_next = NULL; 649145510Sdarrenr free(a); 650145510Sdarrenr} 651145510Sdarrenr 652145510Sdarrenr 653255332Scyint 654255332Scyload_config(file) 655255332Scy char *file; 656145510Sdarrenr{ 657145510Sdarrenr FILE *fp; 658145510Sdarrenr char *s; 659145510Sdarrenr 660255332Scy unload_config(); 661255332Scy 662145510Sdarrenr s = getenv("YYDEBUG"); 663145510Sdarrenr if (s != NULL) 664145510Sdarrenr yydebug = atoi(s); 665145510Sdarrenr else 666145510Sdarrenr yydebug = 0; 667145510Sdarrenr 668145510Sdarrenr yylineNum = 1; 669145510Sdarrenr 670145510Sdarrenr (void) yysettab(yywords); 671145510Sdarrenr 672145510Sdarrenr fp = fopen(file, "r"); 673145510Sdarrenr if (!fp) { 674145510Sdarrenr perror("load_config:fopen:"); 675145510Sdarrenr return -1; 676145510Sdarrenr } 677145510Sdarrenr yyin = fp; 678145510Sdarrenr while (!feof(fp)) 679145510Sdarrenr yyparse(); 680145510Sdarrenr fclose(fp); 681145510Sdarrenr return 0; 682145510Sdarrenr} 683255332Scy 684255332Scy 685255332Scyvoid 686255332Scyunload_config() 687255332Scy{ 688255332Scy ipmon_saver_int_t *sav, **imsip; 689255332Scy ipmon_saver_t *is; 690255332Scy ipmon_action_t *a; 691255332Scy 692255332Scy while ((a = alist) != NULL) { 693255332Scy alist = a->ac_next; 694255332Scy free_action(a); 695255332Scy } 696255332Scy 697255332Scy /* 698255332Scy * Look for savers that have been added in dynamically from the 699255332Scy * configuration file. 700255332Scy */ 701255332Scy for (imsip = &saverlist; (sav = *imsip) != NULL; ) { 702255332Scy if (sav->imsi_handle == NULL) 703255332Scy imsip = &sav->imsi_next; 704255332Scy else { 705255332Scy dlclose(sav->imsi_handle); 706255332Scy 707255332Scy *imsip = sav->imsi_next; 708255332Scy is = sav->imsi_stor; 709255332Scy free(sav); 710255332Scy 711255332Scy free(is->ims_name); 712255332Scy free(is); 713255332Scy } 714255332Scy } 715255332Scy} 716255332Scy 717255332Scy 718255332Scyvoid 719255332Scydump_config() 720255332Scy{ 721255332Scy ipmon_action_t *a; 722255332Scy 723255332Scy for (a = alist; a != NULL; a = a->ac_next) { 724255332Scy print_action(a); 725255332Scy 726255332Scy printf("#\n"); 727255332Scy } 728255332Scy} 729255332Scy 730255332Scy 731255332Scystatic void 732255332Scyprint_action(a) 733255332Scy ipmon_action_t *a; 734255332Scy{ 735255332Scy ipmon_doing_t *d; 736255332Scy 737255332Scy printf("match { "); 738255332Scy print_match(a); 739255332Scy printf("; }\n"); 740255332Scy printf("do {"); 741255332Scy for (d = a->ac_doing; d != NULL; d = d->ipmd_next) { 742255332Scy printf("%s", d->ipmd_saver->ims_name); 743255332Scy if (d->ipmd_saver->ims_print != NULL) { 744255332Scy printf("(\""); 745255332Scy (*d->ipmd_saver->ims_print)(d->ipmd_token); 746255332Scy printf("\")"); 747255332Scy } 748255332Scy printf(";"); 749255332Scy } 750255332Scy printf("};\n"); 751255332Scy} 752255332Scy 753255332Scy 754255332Scyvoid * 755255332Scyadd_doing(saver) 756255332Scy ipmon_saver_t *saver; 757255332Scy{ 758255332Scy ipmon_saver_int_t *it; 759255332Scy 760255332Scy if (find_doing(saver->ims_name) == IPM_DOING) 761255332Scy return NULL; 762255332Scy 763255332Scy it = calloc(1, sizeof(*it)); 764255332Scy if (it == NULL) 765255332Scy return NULL; 766255332Scy it->imsi_stor = saver; 767255332Scy it->imsi_next = saverlist; 768255332Scy saverlist = it; 769255332Scy return it; 770255332Scy} 771255332Scy 772255332Scy 773255332Scystatic int 774255332Scyfind_doing(string) 775255332Scy char *string; 776255332Scy{ 777255332Scy ipmon_saver_int_t *it; 778255332Scy 779255332Scy for (it = saverlist; it != NULL; it = it->imsi_next) { 780255332Scy if (!strcmp(it->imsi_stor->ims_name, string)) 781255332Scy return IPM_DOING; 782255332Scy } 783255332Scy return 0; 784255332Scy} 785255332Scy 786255332Scy 787255332Scystatic ipmon_doing_t * 788255332Scybuild_doing(target, options) 789255332Scy char *target; 790255332Scy char *options; 791255332Scy{ 792255332Scy ipmon_saver_int_t *it; 793255332Scy char *strarray[2]; 794255332Scy ipmon_doing_t *d, *d1; 795255332Scy ipmon_action_t *a; 796255332Scy ipmon_saver_t *save; 797255332Scy 798255332Scy d = calloc(1, sizeof(*d)); 799255332Scy if (d == NULL) 800255332Scy return NULL; 801255332Scy 802255332Scy for (it = saverlist; it != NULL; it = it->imsi_next) { 803255332Scy if (!strcmp(it->imsi_stor->ims_name, target)) 804255332Scy break; 805255332Scy } 806255332Scy if (it == NULL) { 807255332Scy free(d); 808255332Scy return NULL; 809255332Scy } 810255332Scy 811255332Scy strarray[0] = options; 812255332Scy strarray[1] = NULL; 813255332Scy 814255332Scy d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray); 815255332Scy if (d->ipmd_token == NULL) { 816255332Scy free(d); 817255332Scy return NULL; 818255332Scy } 819255332Scy 820255332Scy save = it->imsi_stor; 821255332Scy d->ipmd_saver = save; 822255332Scy d->ipmd_store = it->imsi_stor->ims_store; 823255332Scy 824255332Scy /* 825255332Scy * Look for duplicate do-things that need to be dup'd 826255332Scy */ 827255332Scy for (a = alist; a != NULL; a = a->ac_next) { 828255332Scy for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) { 829255332Scy if (save != d1->ipmd_saver) 830255332Scy continue; 831255332Scy if (save->ims_match == NULL || save->ims_dup == NULL) 832255332Scy continue; 833255332Scy if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token)) 834255332Scy continue; 835255332Scy 836255332Scy (*d->ipmd_saver->ims_destroy)(d->ipmd_token); 837255332Scy d->ipmd_token = (*save->ims_dup)(d1->ipmd_token); 838255332Scy break; 839255332Scy } 840255332Scy } 841255332Scy 842255332Scy return d; 843255332Scy} 844255332Scy 845255332Scy 846255332Scystatic void 847255332Scyprint_match(a) 848255332Scy ipmon_action_t *a; 849255332Scy{ 850255332Scy char *coma = ""; 851255332Scy 852255332Scy if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { 853255332Scy printf("direction = "); 854255332Scy if (a->ac_direction == IPM_IN) 855255332Scy printf("in"); 856255332Scy else if (a->ac_direction == IPM_OUT) 857255332Scy printf("out"); 858255332Scy coma = ", "; 859255332Scy } 860255332Scy 861255332Scy if ((a->ac_mflag & IPMAC_DSTIP) != 0) { 862255332Scy printf("%sdstip = ", coma); 863255332Scy printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk); 864255332Scy coma = ", "; 865255332Scy } 866255332Scy 867255332Scy if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 868255332Scy printf("%sdstport = %hu", coma, ntohs(a->ac_dport)); 869255332Scy coma = ", "; 870255332Scy } 871255332Scy 872255332Scy if ((a->ac_mflag & IPMAC_GROUP) != 0) { 873255332Scy char group[FR_GROUPLEN+1]; 874255332Scy 875255332Scy strncpy(group, a->ac_group, FR_GROUPLEN); 876255332Scy group[FR_GROUPLEN] = '\0'; 877255332Scy printf("%sgroup = %s", coma, group); 878255332Scy coma = ", "; 879255332Scy } 880255332Scy 881255332Scy if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 882255332Scy printf("%siface = %s", coma, a->ac_iface); 883255332Scy coma = ", "; 884255332Scy } 885255332Scy 886255332Scy if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 887255332Scy printf("%slogtag = %u", coma, a->ac_logtag); 888255332Scy coma = ", "; 889255332Scy } 890255332Scy 891255332Scy if ((a->ac_mflag & IPMAC_NATTAG) != 0) { 892255332Scy char tag[17]; 893255332Scy 894255332Scy strncpy(tag, a->ac_nattag, 16); 895255332Scy tag[16] = '\0'; 896255332Scy printf("%snattag = %s", coma, tag); 897255332Scy coma = ", "; 898255332Scy } 899255332Scy 900255332Scy if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { 901255332Scy printf("%sprotocol = %u", coma, a->ac_proto); 902255332Scy coma = ", "; 903255332Scy } 904255332Scy 905255332Scy if ((a->ac_mflag & IPMAC_RESULT) != 0) { 906255332Scy printf("%sresult = ", coma); 907255332Scy switch (a->ac_result) 908255332Scy { 909255332Scy case IPMR_LOG : 910255332Scy printf("log"); 911255332Scy break; 912255332Scy case IPMR_PASS : 913255332Scy printf("pass"); 914255332Scy break; 915255332Scy case IPMR_BLOCK : 916255332Scy printf("block"); 917255332Scy break; 918255332Scy case IPMR_NOMATCH : 919255332Scy printf("nomatch"); 920255332Scy break; 921255332Scy } 922255332Scy coma = ", "; 923255332Scy } 924255332Scy 925255332Scy if ((a->ac_mflag & IPMAC_RULE) != 0) { 926255332Scy printf("%srule = %u", coma, a->ac_rule); 927255332Scy coma = ", "; 928255332Scy } 929255332Scy 930255332Scy if ((a->ac_mflag & IPMAC_EVERY) != 0) { 931255332Scy if (a->ac_packet > 1) { 932255332Scy printf("%severy %d packets", coma, a->ac_packet); 933255332Scy coma = ", "; 934255332Scy } else if (a->ac_packet == 1) { 935255332Scy printf("%severy packet", coma); 936255332Scy coma = ", "; 937255332Scy } 938255332Scy if (a->ac_second > 1) { 939255332Scy printf("%severy %d seconds", coma, a->ac_second); 940255332Scy coma = ", "; 941255332Scy } else if (a->ac_second == 1) { 942255332Scy printf("%severy second", coma); 943255332Scy coma = ", "; 944255332Scy } 945255332Scy } 946255332Scy 947255332Scy if ((a->ac_mflag & IPMAC_SRCIP) != 0) { 948255332Scy printf("%ssrcip = ", coma); 949255332Scy printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk); 950255332Scy coma = ", "; 951255332Scy } 952255332Scy 953255332Scy if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 954255332Scy printf("%ssrcport = %hu", coma, ntohs(a->ac_sport)); 955255332Scy coma = ", "; 956255332Scy } 957255332Scy 958255332Scy if ((a->ac_mflag & IPMAC_TYPE) != 0) { 959255332Scy printf("%stype = ", coma); 960255332Scy switch (a->ac_type) 961255332Scy { 962255332Scy case IPL_LOGIPF : 963255332Scy printf("ipf"); 964255332Scy break; 965255332Scy case IPL_LOGSTATE : 966255332Scy printf("state"); 967255332Scy break; 968255332Scy case IPL_LOGNAT : 969255332Scy printf("nat"); 970255332Scy break; 971255332Scy } 972255332Scy coma = ", "; 973255332Scy } 974255332Scy 975255332Scy if ((a->ac_mflag & IPMAC_WITH) != 0) { 976255332Scy printf("%swith ", coma); 977255332Scy coma = ", "; 978255332Scy } 979255332Scy} 980255332Scy 981255332Scy 982255332Scystatic int 983255332Scyinstall_saver(name, path) 984255332Scy char *name, *path; 985255332Scy{ 986255332Scy ipmon_saver_int_t *isi; 987255332Scy ipmon_saver_t *is; 988255332Scy char nbuf[80]; 989255332Scy 990255332Scy if (find_doing(name) == IPM_DOING) 991255332Scy return -1; 992255332Scy 993255332Scy isi = calloc(1, sizeof(*isi)); 994255332Scy if (isi == NULL) 995255332Scy return -1; 996255332Scy 997255332Scy is = calloc(1, sizeof(*is)); 998255332Scy if (is == NULL) 999255332Scy goto loaderror; 1000255332Scy 1001255332Scy is->ims_name = name; 1002255332Scy 1003255332Scy#ifdef RTLD_LAZY 1004255332Scy isi->imsi_handle = dlopen(path, RTLD_LAZY); 1005255332Scy#endif 1006255332Scy#ifdef DL_LAZY 1007255332Scy isi->imsi_handle = dlopen(path, DL_LAZY); 1008255332Scy#endif 1009255332Scy 1010255332Scy if (isi->imsi_handle == NULL) 1011255332Scy goto loaderror; 1012255332Scy 1013255332Scy snprintf(nbuf, sizeof(nbuf), "%sdup", name); 1014255332Scy is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf); 1015255332Scy 1016255332Scy snprintf(nbuf, sizeof(nbuf), "%sdestroy", name); 1017255332Scy is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf); 1018255332Scy if (is->ims_destroy == NULL) 1019255332Scy goto loaderror; 1020255332Scy 1021255332Scy snprintf(nbuf, sizeof(nbuf), "%smatch", name); 1022255332Scy is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf); 1023255332Scy 1024255332Scy snprintf(nbuf, sizeof(nbuf), "%sparse", name); 1025255332Scy is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf); 1026255332Scy if (is->ims_parse == NULL) 1027255332Scy goto loaderror; 1028255332Scy 1029255332Scy snprintf(nbuf, sizeof(nbuf), "%sprint", name); 1030255332Scy is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf); 1031255332Scy if (is->ims_print == NULL) 1032255332Scy goto loaderror; 1033255332Scy 1034255332Scy snprintf(nbuf, sizeof(nbuf), "%sstore", name); 1035255332Scy is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf); 1036255332Scy if (is->ims_store == NULL) 1037255332Scy goto loaderror; 1038255332Scy 1039255332Scy isi->imsi_stor = is; 1040255332Scy isi->imsi_next = saverlist; 1041255332Scy saverlist = isi; 1042255332Scy 1043255332Scy return 0; 1044255332Scy 1045255332Scyloaderror: 1046255332Scy if (isi->imsi_handle != NULL) 1047255332Scy dlclose(isi->imsi_handle); 1048255332Scy free(isi); 1049255332Scy if (is != NULL) 1050255332Scy free(is); 1051255332Scy return -1; 1052255332Scy} 1053