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 19 extern void yyerror(char *); 20 extern int yyparse(void); 21 extern int yylex(void); 22 extern int yydebug; 23 extern FILE *yyin; 24 extern int yylineNum; 25 extern int ipmonopts; 26 27 typedef 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 38 static void build_action(opt_t *, ipmon_doing_t *); 39 static opt_t *new_opt(int); 40 static void free_action(ipmon_action_t *); 41 static void print_action(ipmon_action_t *); 42 static int find_doing(char *); 43 static ipmon_doing_t *build_doing(char *, char *); 44 static void print_match(ipmon_action_t *); 45 static int install_saver(char *, char *); 46 47 static ipmon_action_t *alist = NULL; 48 49 ipmon_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 %% 82 file: action 83 | file action 84 ; 85 86 action: line ';' 87 | assign ';' 88 | IPM_COMMENT 89 | YY_COMMENT 90 ; 91 92 line: 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 101 assign: YY_STR assigning YY_STR { set_variable($1, $3); 102 resetlexer(); 103 free($1); 104 free($3); 105 yyvarnext = 0; 106 } 107 ; 108 109 assigning: 110 '=' { yyvarnext = 1; } 111 ; 112 113 matching: 114 matchopt { $$ = $1; } 115 | matchopt ',' matching { $1->o_next = $3; $$ = $1; } 116 ; 117 118 matchopt: 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 135 doing: 136 doopt { $$ = $1; } 137 | doopt ',' doing { $1->ipmd_next = $3; $$ = $1; } 138 ; 139 140 doopt: 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 153 direction: 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 160 dstip: IPM_DSTIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_DSTIP); 161 $$->o_ip = $3; 162 $$->o_num = $5; } 163 ; 164 165 dstport: 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 172 every: 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 182 group: 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 188 interface: 189 IPM_INTERFACE '=' YY_STR { $$ = new_opt(IPM_INTERFACE); 190 $$->o_str = $3; } 191 ; 192 193 logtag: IPM_LOGTAG '=' YY_NUMBER { $$ = new_opt(IPM_LOGTAG); 194 $$->o_num = $3; } 195 ; 196 197 nattag: IPM_NATTAG '=' YY_STR { $$ = new_opt(IPM_NATTAG); 198 $$->o_str = $3; } 199 ; 200 201 protocol: 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 210 result: IPM_RESULT '=' YY_STR { $$ = new_opt(IPM_RESULT); 211 $$->o_str = $3; } 212 ; 213 214 rule: IPM_RULE '=' YY_NUMBER { $$ = new_opt(IPM_RULE); 215 $$->o_num = YY_NUMBER; } 216 ; 217 218 srcip: IPM_SRCIP '=' ipv4 '/' YY_NUMBER { $$ = new_opt(IPM_SRCIP); 219 $$->o_ip = $3; 220 $$->o_num = $5; } 221 ; 222 223 srcport: 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 230 type: IPM_TYPE '=' typeopt { $$ = new_opt(IPM_TYPE); 231 $$->o_num = $3; } 232 ; 233 234 typeopt: 235 IPM_IPF { $$ = IPL_MAGIC; } 236 | IPM_NAT { $$ = IPL_MAGIC_NAT; } 237 | IPM_STATE { $$ = IPL_MAGIC_STATE; } 238 ; 239 240 241 242 ipv4: 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 %% 251 static 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 283 static 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 303 static opt_t * 304 new_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 316 static void 317 build_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 428 int 429 check_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 626 static void 627 free_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 646 int 647 load_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 677 void 678 unload_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 710 void 711 dump_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 723 static void 724 print_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 745 void * 746 add_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 763 static int 764 find_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 776 static ipmon_doing_t * 777 build_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 833 static void 834 print_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 968 static int 969 install_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 1030 loaderror: 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