1 2/* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7%{ 8#include "ipf.h" 9#include <syslog.h> 10#undef OPT_NAT 11#undef OPT_VERBOSE 12#include "ipmon_l.h" 13#include "ipmon.h" 14 15#include <dlfcn.h> 16 17#define YYDEBUG 1 18 19extern void yyerror(char *); 20extern int yyparse(void); 21extern int yylex(void); 22extern int yydebug; 23extern FILE *yyin; 24extern int yylineNum; 25extern int ipmonopts; 26 27typedef struct opt_s { 28 struct opt_s *o_next; 29 int o_line; 30 int o_type; 31 int o_num; 32 char *o_str; 33 struct in_addr o_ip; 34 int o_logfac; 35 int o_logpri; 36} opt_t; 37 38static void build_action(opt_t *, ipmon_doing_t *); 39static opt_t *new_opt(int); 40static void free_action(ipmon_action_t *); 41static void print_action(ipmon_action_t *); 42static int find_doing(char *); 43static ipmon_doing_t *build_doing(char *, char *); 44static void print_match(ipmon_action_t *); 45static int install_saver(char *, char *); 46 47static ipmon_action_t *alist = NULL; 48 49ipmon_saver_int_t *saverlist = NULL; 50%} 51 52%union { 53 char *str; 54 u_32_t num; 55 struct in_addr addr; 56 struct opt_s *opt; 57 union i6addr ip6; 58 struct ipmon_doing_s *ipmd; 59} 60 61%token <num> YY_NUMBER YY_HEX 62%token <str> YY_STR 63%token <ip6> YY_IPV6 64%token YY_COMMENT 65%token YY_CMP_EQ YY_CMP_NE YY_CMP_LE YY_CMP_GE YY_CMP_LT YY_CMP_GT 66%token YY_RANGE_OUT YY_RANGE_IN 67 68%token IPM_MATCH IPM_BODY IPM_COMMENT IPM_DIRECTION IPM_DSTIP IPM_DSTPORT 69%token IPM_EVERY IPM_GROUP IPM_INTERFACE IPM_IN IPM_NO IPM_OUT IPM_LOADACTION 70%token IPM_PACKET IPM_PACKETS IPM_POOL IPM_PROTOCOL IPM_RESULT IPM_RULE 71%token IPM_SECOND IPM_SECONDS IPM_SRCIP IPM_SRCPORT IPM_LOGTAG IPM_WITH 72%token IPM_DO IPM_DOING IPM_TYPE IPM_NAT 73%token IPM_STATE IPM_NATTAG IPM_IPF 74%type <addr> ipv4 75%type <opt> direction dstip dstport every group interface 76%type <opt> protocol result rule srcip srcport logtag matching 77%type <opt> matchopt nattag type 78%type <num> typeopt 79%type <ipmd> doopt doing 80 81%% 82file: action 83 | file action 84 ; 85 86action: line ';' 87 | assign ';' 88 | IPM_COMMENT 89 | YY_COMMENT 90 ; 91 92line: IPM_MATCH '{' matching ';' '}' IPM_DO '{' doing ';' '}' 93 { build_action($3, $8); 94 resetlexer(); 95 } 96 | IPM_LOADACTION YY_STR YY_STR { if (install_saver($2, $3)) 97 yyerror("install saver"); 98 } 99 ; 100 101assign: YY_STR assigning YY_STR { set_variable($1, $3); 102 resetlexer(); 103 free($1); 104 free($3); 105 yyvarnext = 0; 106 } 107 ; 108 109assigning: 110 '=' { yyvarnext = 1; } 111 ; 112 113matching: 114 matchopt { $$ = $1; } 115 | matchopt ',' matching { $1->o_next = $3; $$ = $1; } 116 ; 117 118matchopt: 119 direction { $$ = $1; } 120 | dstip { $$ = $1; } 121 | dstport { $$ = $1; } 122 | every { $$ = $1; } 123 | group { $$ = $1; } 124 | interface { $$ = $1; } 125 | protocol { $$ = $1; } 126 | result { $$ = $1; } 127 | rule { $$ = $1; } 128 | srcip { $$ = $1; } 129 | srcport { $$ = $1; } 130 | logtag { $$ = $1; } 131 | nattag { $$ = $1; } 132 | type { $$ = $1; } 133 ; 134 135doing: 136 doopt { $$ = $1; } 137 | doopt ',' doing { $1->ipmd_next = $3; $$ = $1; } 138 ; 139 140doopt: 141 YY_STR { if (find_doing($1) != IPM_DOING) 142 yyerror("unknown action"); 143 } 144 '(' YY_STR ')' { $$ = build_doing($1, $4); 145 if ($$ == NULL) 146 yyerror("action building"); 147 } 148 | YY_STR { if (find_doing($1) == IPM_DOING) 149 $$ = build_doing($1, NULL); 150 } 151 ; 152 153direction: 154 IPM_DIRECTION '=' IPM_IN { $$ = new_opt(IPM_DIRECTION); 155 $$->o_num = IPM_IN; } 156 | IPM_DIRECTION '=' IPM_OUT { $$ = new_opt(IPM_DIRECTION); 157 $$->o_num = IPM_OUT; } 158 ; 159 160dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP); 161 $$->o_ip = $3; 162 $$->o_num = $5; } 163 ; 164 165dstport: 166 IPM_DSTPORT '=' YY_NUMBER { $$ = new_opt(IPM_DSTPORT); 167 $$->o_num = $3; } 168 | IPM_DSTPORT '=' YY_STR { $$ = new_opt(IPM_DSTPORT); 169 $$->o_str = $3; } 170 ; 171 172every: IPM_EVERY IPM_SECOND { $$ = new_opt(IPM_SECOND); 173 $$->o_num = 1; } 174 | IPM_EVERY YY_NUMBER IPM_SECONDS { $$ = new_opt(IPM_SECOND); 175 $$->o_num = $2; } 176 | IPM_EVERY IPM_PACKET { $$ = new_opt(IPM_PACKET); 177 $$->o_num = 1; } 178 | IPM_EVERY YY_NUMBER IPM_PACKETS { $$ = new_opt(IPM_PACKET); 179 $$->o_num = $2; } 180 ; 181 182group: IPM_GROUP '=' YY_NUMBER { $$ = new_opt(IPM_GROUP); 183 $$->o_num = $3; } 184 | IPM_GROUP '=' YY_STR { $$ = new_opt(IPM_GROUP); 185 $$->o_str = $3; } 186 ; 187 188interface: 189 IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE); 190 $$->o_str = $3; } 191 ; 192 193logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG); 194 $$->o_num = $3; } 195 ; 196 197nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG); 198 $$->o_str = $3; } 199 ; 200 201protocol: 202 IPM_PROTOCOL '=' YY_NUMBER { $$ = new_opt(IPM_PROTOCOL); 203 $$->o_num = $3; } 204 | IPM_PROTOCOL '=' YY_STR { $$ = new_opt(IPM_PROTOCOL); 205 $$->o_num = getproto($3); 206 free($3); 207 } 208 ; 209 210result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT); 211 $$->o_str = $3; } 212 ; 213 214rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE); 215 $$->o_num = YY_NUMBER; } 216 ; 217 218srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP); 219 $$->o_ip = $3; 220 $$->o_num = $5; } 221 ; 222 223srcport: 224 IPM_SRCPORT '=' YY_NUMBER { $$ = new_opt(IPM_SRCPORT); 225 $$->o_num = $3; } 226 | IPM_SRCPORT '=' YY_STR { $$ = new_opt(IPM_SRCPORT); 227 $$->o_str = $3; } 228 ; 229 230type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE); 231 $$->o_num = $3; } 232 ; 233 234typeopt: 235 IPM_IPF { $$ = IPL_MAGIC; } 236 | IPM_NAT { $$ = IPL_MAGIC_NAT; } 237 | IPM_STATE { $$ = IPL_MAGIC_STATE; } 238 ; 239 240 241 242ipv4: YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER '.' YY_NUMBER 243 { if ($1 > 255 || $3 > 255 || $5 > 255 || $7 > 255) { 244 yyerror("Invalid octet string for IP address"); 245 return(0); 246 } 247 $$.s_addr = ($1 << 24) | ($3 << 16) | ($5 << 8) | $7; 248 $$.s_addr = htonl($$.s_addr); 249 } 250%% 251static struct wordtab yywords[] = { 252 { "body", IPM_BODY }, 253 { "direction", IPM_DIRECTION }, 254 { "do", IPM_DO }, 255 { "dstip", IPM_DSTIP }, 256 { "dstport", IPM_DSTPORT }, 257 { "every", IPM_EVERY }, 258 { "group", IPM_GROUP }, 259 { "in", IPM_IN }, 260 { "interface", IPM_INTERFACE }, 261 { "ipf", IPM_IPF }, 262 { "load_action",IPM_LOADACTION }, 263 { "logtag", IPM_LOGTAG }, 264 { "match", IPM_MATCH }, 265 { "nat", IPM_NAT }, 266 { "nattag", IPM_NATTAG }, 267 { "no", IPM_NO }, 268 { "out", IPM_OUT }, 269 { "packet", IPM_PACKET }, 270 { "packets", IPM_PACKETS }, 271 { "protocol", IPM_PROTOCOL }, 272 { "result", IPM_RESULT }, 273 { "rule", IPM_RULE }, 274 { "second", IPM_SECOND }, 275 { "seconds", IPM_SECONDS }, 276 { "srcip", IPM_SRCIP }, 277 { "srcport", IPM_SRCPORT }, 278 { "state", IPM_STATE }, 279 { "with", IPM_WITH }, 280 { NULL, 0 } 281}; 282 283static int macflags[17][2] = { 284 { IPM_DIRECTION, IPMAC_DIRECTION }, 285 { IPM_DSTIP, IPMAC_DSTIP }, 286 { IPM_DSTPORT, IPMAC_DSTPORT }, 287 { IPM_GROUP, IPMAC_GROUP }, 288 { IPM_INTERFACE, IPMAC_INTERFACE }, 289 { IPM_LOGTAG, IPMAC_LOGTAG }, 290 { IPM_NATTAG, IPMAC_NATTAG }, 291 { IPM_PACKET, IPMAC_EVERY }, 292 { IPM_PROTOCOL, IPMAC_PROTOCOL }, 293 { IPM_RESULT, IPMAC_RESULT }, 294 { IPM_RULE, IPMAC_RULE }, 295 { IPM_SECOND, IPMAC_EVERY }, 296 { IPM_SRCIP, IPMAC_SRCIP }, 297 { IPM_SRCPORT, IPMAC_SRCPORT }, 298 { IPM_TYPE, IPMAC_TYPE }, 299 { IPM_WITH, IPMAC_WITH }, 300 { 0, 0 } 301}; 302 303static opt_t * 304new_opt(int type) 305{ 306 opt_t *o; 307 308 o = (opt_t *)calloc(1, sizeof(*o)); 309 o->o_type = type; 310 o->o_line = yylineNum; 311 o->o_logfac = -1; 312 o->o_logpri = -1; 313 return(o); 314} 315 316static void 317build_action(opt_t *olist, ipmon_doing_t *todo) 318{ 319 ipmon_action_t *a; 320 opt_t *o; 321 int i; 322 323 a = (ipmon_action_t *)calloc(1, sizeof(*a)); 324 if (a == NULL) 325 return; 326 327 while ((o = olist) != NULL) { 328 /* 329 * Check to see if the same comparator is being used more than 330 * once per matching statement. 331 */ 332 for (i = 0; macflags[i][0]; i++) 333 if (macflags[i][0] == o->o_type) 334 break; 335 if (macflags[i][1] & a->ac_mflag) { 336 fprintf(stderr, "%s redfined on line %d\n", 337 yykeytostr(o->o_type), yylineNum); 338 if (o->o_str != NULL) 339 free(o->o_str); 340 olist = o->o_next; 341 free(o); 342 continue; 343 } 344 345 a->ac_mflag |= macflags[i][1]; 346 347 switch (o->o_type) 348 { 349 case IPM_DIRECTION : 350 a->ac_direction = o->o_num; 351 break; 352 case IPM_DSTIP : 353 a->ac_dip = o->o_ip.s_addr; 354 a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num)); 355 break; 356 case IPM_DSTPORT : 357 a->ac_dport = htons(o->o_num); 358 break; 359 case IPM_INTERFACE : 360 a->ac_iface = o->o_str; 361 o->o_str = NULL; 362 break; 363 case IPM_GROUP : 364 if (o->o_str != NULL) 365 strncpy(a->ac_group, o->o_str, FR_GROUPLEN); 366 else 367 sprintf(a->ac_group, "%d", o->o_num); 368 break; 369 case IPM_LOGTAG : 370 a->ac_logtag = o->o_num; 371 break; 372 case IPM_NATTAG : 373 strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag)); 374 break; 375 case IPM_PACKET : 376 a->ac_packet = o->o_num; 377 break; 378 case IPM_PROTOCOL : 379 a->ac_proto = o->o_num; 380 break; 381 case IPM_RULE : 382 a->ac_rule = o->o_num; 383 break; 384 case IPM_RESULT : 385 if (!strcasecmp(o->o_str, "pass")) 386 a->ac_result = IPMR_PASS; 387 else if (!strcasecmp(o->o_str, "block")) 388 a->ac_result = IPMR_BLOCK; 389 else if (!strcasecmp(o->o_str, "nomatch")) 390 a->ac_result = IPMR_NOMATCH; 391 else if (!strcasecmp(o->o_str, "log")) 392 a->ac_result = IPMR_LOG; 393 break; 394 case IPM_SECOND : 395 a->ac_second = o->o_num; 396 break; 397 case IPM_SRCIP : 398 a->ac_sip = o->o_ip.s_addr; 399 a->ac_smsk = htonl(0xffffffff << (32 - o->o_num)); 400 break; 401 case IPM_SRCPORT : 402 a->ac_sport = htons(o->o_num); 403 break; 404 case IPM_TYPE : 405 a->ac_type = o->o_num; 406 break; 407 case IPM_WITH : 408 break; 409 default : 410 break; 411 } 412 413 olist = o->o_next; 414 if (o->o_str != NULL) 415 free(o->o_str); 416 free(o); 417 } 418 419 a->ac_doing = todo; 420 a->ac_next = alist; 421 alist = a; 422 423 if (ipmonopts & IPMON_VERBOSE) 424 print_action(a); 425} 426 427 428int 429check_action(char *buf, char *log, int opts, int lvl) 430{ 431 ipmon_action_t *a; 432 struct timeval tv; 433 ipmon_doing_t *d; 434 ipmon_msg_t msg; 435 ipflog_t *ipf; 436 tcphdr_t *tcp; 437 iplog_t *ipl; 438 int matched; 439 u_long t1; 440 ip_t *ip; 441 442 matched = 0; 443 ipl = (iplog_t *)buf; 444 ipf = (ipflog_t *)(ipl +1); 445 ip = (ip_t *)(ipf + 1); 446 tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); 447 448 msg.imm_data = ipl; 449 msg.imm_dsize = ipl->ipl_dsize; 450 msg.imm_when = ipl->ipl_time.tv_sec; 451 msg.imm_msg = log; 452 msg.imm_msglen = strlen(log); 453 msg.imm_loglevel = lvl; 454 455 for (a = alist; a != NULL; a = a->ac_next) { 456 verbose(0, "== checking config rule\n"); 457 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { 458 if (a->ac_direction == IPM_IN) { 459 if ((ipf->fl_flags & FR_INQUE) == 0) { 460 verbose(8, "-- direction not in\n"); 461 continue; 462 } 463 } else if (a->ac_direction == IPM_OUT) { 464 if ((ipf->fl_flags & FR_OUTQUE) == 0) { 465 verbose(8, "-- direction not out\n"); 466 continue; 467 } 468 } 469 } 470 471 if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) { 472 verbose(8, "-- type mismatch\n"); 473 continue; 474 } 475 476 if ((a->ac_mflag & IPMAC_EVERY) != 0) { 477 gettimeofday(&tv, NULL); 478 t1 = tv.tv_sec - a->ac_lastsec; 479 if (tv.tv_usec <= a->ac_lastusec) 480 t1--; 481 if (a->ac_second != 0) { 482 if (t1 < a->ac_second) { 483 verbose(8, "-- too soon\n"); 484 continue; 485 } 486 a->ac_lastsec = tv.tv_sec; 487 a->ac_lastusec = tv.tv_usec; 488 } 489 490 if (a->ac_packet != 0) { 491 if (a->ac_pktcnt == 0) 492 a->ac_pktcnt++; 493 else if (a->ac_pktcnt == a->ac_packet) { 494 a->ac_pktcnt = 0; 495 verbose(8, "-- packet count\n"); 496 continue; 497 } else { 498 a->ac_pktcnt++; 499 verbose(8, "-- packet count\n"); 500 continue; 501 } 502 } 503 } 504 505 if ((a->ac_mflag & IPMAC_DSTIP) != 0) { 506 if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) { 507 verbose(8, "-- dstip wrong\n"); 508 continue; 509 } 510 } 511 512 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 513 if (ip->ip_p != IPPROTO_UDP && 514 ip->ip_p != IPPROTO_TCP) { 515 verbose(8, "-- not port protocol\n"); 516 continue; 517 } 518 if (tcp->th_dport != a->ac_dport) { 519 verbose(8, "-- dport mismatch\n"); 520 continue; 521 } 522 } 523 524 if ((a->ac_mflag & IPMAC_GROUP) != 0) { 525 if (strncmp(a->ac_group, ipf->fl_group, 526 FR_GROUPLEN) != 0) { 527 verbose(8, "-- group mismatch\n"); 528 continue; 529 } 530 } 531 532 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 533 if (strcmp(a->ac_iface, ipf->fl_ifname)) { 534 verbose(8, "-- ifname mismatch\n"); 535 continue; 536 } 537 } 538 539 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { 540 if (a->ac_proto != ip->ip_p) { 541 verbose(8, "-- protocol mismatch\n"); 542 continue; 543 } 544 } 545 546 if ((a->ac_mflag & IPMAC_RESULT) != 0) { 547 if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) { 548 if (a->ac_result != IPMR_NOMATCH) { 549 verbose(8, "-- ff-flags mismatch\n"); 550 continue; 551 } 552 } else if (FR_ISPASS(ipf->fl_flags)) { 553 if (a->ac_result != IPMR_PASS) { 554 verbose(8, "-- pass mismatch\n"); 555 continue; 556 } 557 } else if (FR_ISBLOCK(ipf->fl_flags)) { 558 if (a->ac_result != IPMR_BLOCK) { 559 verbose(8, "-- block mismatch\n"); 560 continue; 561 } 562 } else { /* Log only */ 563 if (a->ac_result != IPMR_LOG) { 564 verbose(8, "-- log mismatch\n"); 565 continue; 566 } 567 } 568 } 569 570 if ((a->ac_mflag & IPMAC_RULE) != 0) { 571 if (a->ac_rule != ipf->fl_rule) { 572 verbose(8, "-- rule mismatch\n"); 573 continue; 574 } 575 } 576 577 if ((a->ac_mflag & IPMAC_SRCIP) != 0) { 578 if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) { 579 verbose(8, "-- srcip mismatch\n"); 580 continue; 581 } 582 } 583 584 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 585 if (ip->ip_p != IPPROTO_UDP && 586 ip->ip_p != IPPROTO_TCP) { 587 verbose(8, "-- port protocol mismatch\n"); 588 continue; 589 } 590 if (tcp->th_sport != a->ac_sport) { 591 verbose(8, "-- sport mismatch\n"); 592 continue; 593 } 594 } 595 596 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 597 if (a->ac_logtag != ipf->fl_logtag) { 598 verbose(8, "-- logtag %d != %d\n", 599 a->ac_logtag, ipf->fl_logtag); 600 continue; 601 } 602 } 603 604 if ((a->ac_mflag & IPMAC_NATTAG) != 0) { 605 if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag, 606 IPFTAG_LEN) != 0) { 607 verbose(8, "-- nattag mismatch\n"); 608 continue; 609 } 610 } 611 612 matched = 1; 613 verbose(8, "++ matched\n"); 614 615 /* 616 * It matched so now perform the saves 617 */ 618 for (d = a->ac_doing; d != NULL; d = d->ipmd_next) 619 (*d->ipmd_store)(d->ipmd_token, &msg); 620 } 621 622 return(matched); 623} 624 625 626static void 627free_action(ipmon_action_t *a) 628{ 629 ipmon_doing_t *d; 630 631 while ((d = a->ac_doing) != NULL) { 632 a->ac_doing = d->ipmd_next; 633 (*d->ipmd_saver->ims_destroy)(d->ipmd_token); 634 free(d); 635 } 636 637 if (a->ac_iface != NULL) { 638 free(a->ac_iface); 639 a->ac_iface = NULL; 640 } 641 a->ac_next = NULL; 642 free(a); 643} 644 645 646int 647load_config(char *file) 648{ 649 FILE *fp; 650 char *s; 651 652 unload_config(); 653 654 s = getenv("YYDEBUG"); 655 if (s != NULL) 656 yydebug = atoi(s); 657 else 658 yydebug = 0; 659 660 yylineNum = 1; 661 662 (void) yysettab(yywords); 663 664 fp = fopen(file, "r"); 665 if (!fp) { 666 perror("load_config:fopen:"); 667 return(-1); 668 } 669 yyin = fp; 670 while (!feof(fp)) 671 yyparse(); 672 fclose(fp); 673 return(0); 674} 675 676 677void 678unload_config(void) 679{ 680 ipmon_saver_int_t *sav, **imsip; 681 ipmon_saver_t *is; 682 ipmon_action_t *a; 683 684 while ((a = alist) != NULL) { 685 alist = a->ac_next; 686 free_action(a); 687 } 688 689 /* 690 * Look for savers that have been added in dynamically from the 691 * configuration file. 692 */ 693 for (imsip = &saverlist; (sav = *imsip) != NULL; ) { 694 if (sav->imsi_handle == NULL) 695 imsip = &sav->imsi_next; 696 else { 697 dlclose(sav->imsi_handle); 698 699 *imsip = sav->imsi_next; 700 is = sav->imsi_stor; 701 free(sav); 702 703 free(is->ims_name); 704 free(is); 705 } 706 } 707} 708 709 710void 711dump_config(void) 712{ 713 ipmon_action_t *a; 714 715 for (a = alist; a != NULL; a = a->ac_next) { 716 print_action(a); 717 718 printf("#\n"); 719 } 720} 721 722 723static void 724print_action(ipmon_action_t *a) 725{ 726 ipmon_doing_t *d; 727 728 printf("match { "); 729 print_match(a); 730 printf("; }\n"); 731 printf("do {"); 732 for (d = a->ac_doing; d != NULL; d = d->ipmd_next) { 733 printf("%s", d->ipmd_saver->ims_name); 734 if (d->ipmd_saver->ims_print != NULL) { 735 printf("(\""); 736 (*d->ipmd_saver->ims_print)(d->ipmd_token); 737 printf("\")"); 738 } 739 printf(";"); 740 } 741 printf("};\n"); 742} 743 744 745void * 746add_doing(ipmon_saver_t *saver) 747{ 748 ipmon_saver_int_t *it; 749 750 if (find_doing(saver->ims_name) == IPM_DOING) 751 return(NULL); 752 753 it = calloc(1, sizeof(*it)); 754 if (it == NULL) 755 return(NULL); 756 it->imsi_stor = saver; 757 it->imsi_next = saverlist; 758 saverlist = it; 759 return(it); 760} 761 762 763static int 764find_doing(char *string) 765{ 766 ipmon_saver_int_t *it; 767 768 for (it = saverlist; it != NULL; it = it->imsi_next) { 769 if (!strcmp(it->imsi_stor->ims_name, string)) 770 return(IPM_DOING); 771 } 772 return(0); 773} 774 775 776static ipmon_doing_t * 777build_doing(char *target, char *options) 778{ 779 ipmon_saver_int_t *it; 780 char *strarray[2]; 781 ipmon_doing_t *d, *d1; 782 ipmon_action_t *a; 783 ipmon_saver_t *save; 784 785 d = calloc(1, sizeof(*d)); 786 if (d == NULL) 787 return(NULL); 788 789 for (it = saverlist; it != NULL; it = it->imsi_next) { 790 if (!strcmp(it->imsi_stor->ims_name, target)) 791 break; 792 } 793 if (it == NULL) { 794 free(d); 795 return(NULL); 796 } 797 798 strarray[0] = options; 799 strarray[1] = NULL; 800 801 d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray); 802 if (d->ipmd_token == NULL) { 803 free(d); 804 return(NULL); 805 } 806 807 save = it->imsi_stor; 808 d->ipmd_saver = save; 809 d->ipmd_store = it->imsi_stor->ims_store; 810 811 /* 812 * Look for duplicate do-things that need to be dup'd 813 */ 814 for (a = alist; a != NULL; a = a->ac_next) { 815 for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) { 816 if (save != d1->ipmd_saver) 817 continue; 818 if (save->ims_match == NULL || save->ims_dup == NULL) 819 continue; 820 if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token)) 821 continue; 822 823 (*d->ipmd_saver->ims_destroy)(d->ipmd_token); 824 d->ipmd_token = (*save->ims_dup)(d1->ipmd_token); 825 break; 826 } 827 } 828 829 return(d); 830} 831 832 833static void 834print_match(ipmon_action_t *a) 835{ 836 char *coma = ""; 837 838 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { 839 printf("direction = "); 840 if (a->ac_direction == IPM_IN) 841 printf("in"); 842 else if (a->ac_direction == IPM_OUT) 843 printf("out"); 844 coma = ", "; 845 } 846 847 if ((a->ac_mflag & IPMAC_DSTIP) != 0) { 848 printf("%sdstip = ", coma); 849 printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk); 850 coma = ", "; 851 } 852 853 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 854 printf("%sdstport = %hu", coma, ntohs(a->ac_dport)); 855 coma = ", "; 856 } 857 858 if ((a->ac_mflag & IPMAC_GROUP) != 0) { 859 char group[FR_GROUPLEN+1]; 860 861 strncpy(group, a->ac_group, FR_GROUPLEN); 862 group[FR_GROUPLEN] = '\0'; 863 printf("%sgroup = %s", coma, group); 864 coma = ", "; 865 } 866 867 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 868 printf("%siface = %s", coma, a->ac_iface); 869 coma = ", "; 870 } 871 872 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 873 printf("%slogtag = %u", coma, a->ac_logtag); 874 coma = ", "; 875 } 876 877 if ((a->ac_mflag & IPMAC_NATTAG) != 0) { 878 char tag[17]; 879 880 strncpy(tag, a->ac_nattag, 16); 881 tag[16] = '\0'; 882 printf("%snattag = %s", coma, tag); 883 coma = ", "; 884 } 885 886 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { 887 printf("%sprotocol = %u", coma, a->ac_proto); 888 coma = ", "; 889 } 890 891 if ((a->ac_mflag & IPMAC_RESULT) != 0) { 892 printf("%sresult = ", coma); 893 switch (a->ac_result) 894 { 895 case IPMR_LOG : 896 printf("log"); 897 break; 898 case IPMR_PASS : 899 printf("pass"); 900 break; 901 case IPMR_BLOCK : 902 printf("block"); 903 break; 904 case IPMR_NOMATCH : 905 printf("nomatch"); 906 break; 907 } 908 coma = ", "; 909 } 910 911 if ((a->ac_mflag & IPMAC_RULE) != 0) { 912 printf("%srule = %u", coma, a->ac_rule); 913 coma = ", "; 914 } 915 916 if ((a->ac_mflag & IPMAC_EVERY) != 0) { 917 if (a->ac_packet > 1) { 918 printf("%severy %d packets", coma, a->ac_packet); 919 coma = ", "; 920 } else if (a->ac_packet == 1) { 921 printf("%severy packet", coma); 922 coma = ", "; 923 } 924 if (a->ac_second > 1) { 925 printf("%severy %d seconds", coma, a->ac_second); 926 coma = ", "; 927 } else if (a->ac_second == 1) { 928 printf("%severy second", coma); 929 coma = ", "; 930 } 931 } 932 933 if ((a->ac_mflag & IPMAC_SRCIP) != 0) { 934 printf("%ssrcip = ", coma); 935 printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk); 936 coma = ", "; 937 } 938 939 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 940 printf("%ssrcport = %hu", coma, ntohs(a->ac_sport)); 941 coma = ", "; 942 } 943 944 if ((a->ac_mflag & IPMAC_TYPE) != 0) { 945 printf("%stype = ", coma); 946 switch (a->ac_type) 947 { 948 case IPL_LOGIPF : 949 printf("ipf"); 950 break; 951 case IPL_LOGSTATE : 952 printf("state"); 953 break; 954 case IPL_LOGNAT : 955 printf("nat"); 956 break; 957 } 958 coma = ", "; 959 } 960 961 if ((a->ac_mflag & IPMAC_WITH) != 0) { 962 printf("%swith ", coma); 963 coma = ", "; 964 } 965} 966 967 968static int 969install_saver(char *name, char *path) 970{ 971 ipmon_saver_int_t *isi; 972 ipmon_saver_t *is; 973 char nbuf[80]; 974 975 if (find_doing(name) == IPM_DOING) 976 return(-1); 977 978 isi = calloc(1, sizeof(*isi)); 979 if (isi == NULL) 980 return(-1); 981 982 is = calloc(1, sizeof(*is)); 983 if (is == NULL) 984 goto loaderror; 985 986 is->ims_name = name; 987 988#ifdef RTLD_LAZY 989 isi->imsi_handle = dlopen(path, RTLD_LAZY); 990#endif 991#ifdef DL_LAZY 992 isi->imsi_handle = dlopen(path, DL_LAZY); 993#endif 994 995 if (isi->imsi_handle == NULL) 996 goto loaderror; 997 998 snprintf(nbuf, sizeof(nbuf), "%sdup", name); 999 is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf); 1000 1001 snprintf(nbuf, sizeof(nbuf), "%sdestroy", name); 1002 is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf); 1003 if (is->ims_destroy == NULL) 1004 goto loaderror; 1005 1006 snprintf(nbuf, sizeof(nbuf), "%smatch", name); 1007 is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf); 1008 1009 snprintf(nbuf, sizeof(nbuf), "%sparse", name); 1010 is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf); 1011 if (is->ims_parse == NULL) 1012 goto loaderror; 1013 1014 snprintf(nbuf, sizeof(nbuf), "%sprint", name); 1015 is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf); 1016 if (is->ims_print == NULL) 1017 goto loaderror; 1018 1019 snprintf(nbuf, sizeof(nbuf), "%sstore", name); 1020 is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf); 1021 if (is->ims_store == NULL) 1022 goto loaderror; 1023 1024 isi->imsi_stor = is; 1025 isi->imsi_next = saverlist; 1026 saverlist = isi; 1027 1028 return(0); 1029 1030loaderror: 1031 if (isi->imsi_handle != NULL) 1032 dlclose(isi->imsi_handle); 1033 free(isi); 1034 if (is != NULL) 1035 free(is); 1036 return(-1); 1037} 1038