/* $FreeBSD$ */ /* * Copyright (C) 2012 by Darren Reed. * * See the IPFILTER.LICENCE file for details on licencing. */ %{ #include "ipf.h" #include #undef OPT_NAT #undef OPT_VERBOSE #include "ipmon_l.h" #include "ipmon.h" #include #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 YY_NUMBER YY_HEX %token YY_STR %token 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 ipv4 %type direction dstip dstport every group interface %type protocol result rule srcip srcport logtag matching %type matchopt nattag type %type typeopt %type 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); }