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