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(int type) 306 { 307 opt_t *o; 308 309 o = (opt_t *)calloc(1, sizeof(*o)); 310 o->o_type = type; 311 o->o_line = yylineNum; 312 o->o_logfac = -1; 313 o->o_logpri = -1; 314 return(o); 315 } 316 317 static void 318 build_action(opt_t *olist, ipmon_doing_t *todo) 319 { 320 ipmon_action_t *a; 321 opt_t *o; 322 int i; 323 324 a = (ipmon_action_t *)calloc(1, sizeof(*a)); 325 if (a == NULL) 326 return; 327 328 while ((o = olist) != NULL) { 329 /* 330 * Check to see if the same comparator is being used more than 331 * once per matching statement. 332 */ 333 for (i = 0; macflags[i][0]; i++) 334 if (macflags[i][0] == o->o_type) 335 break; 336 if (macflags[i][1] & a->ac_mflag) { 337 fprintf(stderr, "%s redfined on line %d\n", 338 yykeytostr(o->o_type), yylineNum); 339 if (o->o_str != NULL) 340 free(o->o_str); 341 olist = o->o_next; 342 free(o); 343 continue; 344 } 345 346 a->ac_mflag |= macflags[i][1]; 347 348 switch (o->o_type) 349 { 350 case IPM_DIRECTION : 351 a->ac_direction = o->o_num; 352 break; 353 case IPM_DSTIP : 354 a->ac_dip = o->o_ip.s_addr; 355 a->ac_dmsk = htonl(0xffffffff << (32 - o->o_num)); 356 break; 357 case IPM_DSTPORT : 358 a->ac_dport = htons(o->o_num); 359 break; 360 case IPM_INTERFACE : 361 a->ac_iface = o->o_str; 362 o->o_str = NULL; 363 break; 364 case IPM_GROUP : 365 if (o->o_str != NULL) 366 strncpy(a->ac_group, o->o_str, FR_GROUPLEN); 367 else 368 sprintf(a->ac_group, "%d", o->o_num); 369 break; 370 case IPM_LOGTAG : 371 a->ac_logtag = o->o_num; 372 break; 373 case IPM_NATTAG : 374 strncpy(a->ac_nattag, o->o_str, sizeof(a->ac_nattag)); 375 break; 376 case IPM_PACKET : 377 a->ac_packet = o->o_num; 378 break; 379 case IPM_PROTOCOL : 380 a->ac_proto = o->o_num; 381 break; 382 case IPM_RULE : 383 a->ac_rule = o->o_num; 384 break; 385 case IPM_RESULT : 386 if (!strcasecmp(o->o_str, "pass")) 387 a->ac_result = IPMR_PASS; 388 else if (!strcasecmp(o->o_str, "block")) 389 a->ac_result = IPMR_BLOCK; 390 else if (!strcasecmp(o->o_str, "nomatch")) 391 a->ac_result = IPMR_NOMATCH; 392 else if (!strcasecmp(o->o_str, "log")) 393 a->ac_result = IPMR_LOG; 394 break; 395 case IPM_SECOND : 396 a->ac_second = o->o_num; 397 break; 398 case IPM_SRCIP : 399 a->ac_sip = o->o_ip.s_addr; 400 a->ac_smsk = htonl(0xffffffff << (32 - o->o_num)); 401 break; 402 case IPM_SRCPORT : 403 a->ac_sport = htons(o->o_num); 404 break; 405 case IPM_TYPE : 406 a->ac_type = o->o_num; 407 break; 408 case IPM_WITH : 409 break; 410 default : 411 break; 412 } 413 414 olist = o->o_next; 415 if (o->o_str != NULL) 416 free(o->o_str); 417 free(o); 418 } 419 420 a->ac_doing = todo; 421 a->ac_next = alist; 422 alist = a; 423 424 if (ipmonopts & IPMON_VERBOSE) 425 print_action(a); 426 } 427 428 429 int 430 check_action(char *buf, char *log, int opts, int lvl) 431 { 432 ipmon_action_t *a; 433 struct timeval tv; 434 ipmon_doing_t *d; 435 ipmon_msg_t msg; 436 ipflog_t *ipf; 437 tcphdr_t *tcp; 438 iplog_t *ipl; 439 int matched; 440 u_long t1; 441 ip_t *ip; 442 443 matched = 0; 444 ipl = (iplog_t *)buf; 445 ipf = (ipflog_t *)(ipl +1); 446 ip = (ip_t *)(ipf + 1); 447 tcp = (tcphdr_t *)((char *)ip + (IP_HL(ip) << 2)); 448 449 msg.imm_data = ipl; 450 msg.imm_dsize = ipl->ipl_dsize; 451 msg.imm_when = ipl->ipl_time.tv_sec; 452 msg.imm_msg = log; 453 msg.imm_msglen = strlen(log); 454 msg.imm_loglevel = lvl; 455 456 for (a = alist; a != NULL; a = a->ac_next) { 457 verbose(0, "== checking config rule\n"); 458 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { 459 if (a->ac_direction == IPM_IN) { 460 if ((ipf->fl_flags & FR_INQUE) == 0) { 461 verbose(8, "-- direction not in\n"); 462 continue; 463 } 464 } else if (a->ac_direction == IPM_OUT) { 465 if ((ipf->fl_flags & FR_OUTQUE) == 0) { 466 verbose(8, "-- direction not out\n"); 467 continue; 468 } 469 } 470 } 471 472 if ((a->ac_type != 0) && (a->ac_type != ipl->ipl_magic)) { 473 verbose(8, "-- type mismatch\n"); 474 continue; 475 } 476 477 if ((a->ac_mflag & IPMAC_EVERY) != 0) { 478 gettimeofday(&tv, NULL); 479 t1 = tv.tv_sec - a->ac_lastsec; 480 if (tv.tv_usec <= a->ac_lastusec) 481 t1--; 482 if (a->ac_second != 0) { 483 if (t1 < a->ac_second) { 484 verbose(8, "-- too soon\n"); 485 continue; 486 } 487 a->ac_lastsec = tv.tv_sec; 488 a->ac_lastusec = tv.tv_usec; 489 } 490 491 if (a->ac_packet != 0) { 492 if (a->ac_pktcnt == 0) 493 a->ac_pktcnt++; 494 else if (a->ac_pktcnt == a->ac_packet) { 495 a->ac_pktcnt = 0; 496 verbose(8, "-- packet count\n"); 497 continue; 498 } else { 499 a->ac_pktcnt++; 500 verbose(8, "-- packet count\n"); 501 continue; 502 } 503 } 504 } 505 506 if ((a->ac_mflag & IPMAC_DSTIP) != 0) { 507 if ((ip->ip_dst.s_addr & a->ac_dmsk) != a->ac_dip) { 508 verbose(8, "-- dstip wrong\n"); 509 continue; 510 } 511 } 512 513 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 514 if (ip->ip_p != IPPROTO_UDP && 515 ip->ip_p != IPPROTO_TCP) { 516 verbose(8, "-- not port protocol\n"); 517 continue; 518 } 519 if (tcp->th_dport != a->ac_dport) { 520 verbose(8, "-- dport mismatch\n"); 521 continue; 522 } 523 } 524 525 if ((a->ac_mflag & IPMAC_GROUP) != 0) { 526 if (strncmp(a->ac_group, ipf->fl_group, 527 FR_GROUPLEN) != 0) { 528 verbose(8, "-- group mismatch\n"); 529 continue; 530 } 531 } 532 533 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 534 if (strcmp(a->ac_iface, ipf->fl_ifname)) { 535 verbose(8, "-- ifname mismatch\n"); 536 continue; 537 } 538 } 539 540 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { 541 if (a->ac_proto != ip->ip_p) { 542 verbose(8, "-- protocol mismatch\n"); 543 continue; 544 } 545 } 546 547 if ((a->ac_mflag & IPMAC_RESULT) != 0) { 548 if ((ipf->fl_flags & FF_LOGNOMATCH) != 0) { 549 if (a->ac_result != IPMR_NOMATCH) { 550 verbose(8, "-- ff-flags mismatch\n"); 551 continue; 552 } 553 } else if (FR_ISPASS(ipf->fl_flags)) { 554 if (a->ac_result != IPMR_PASS) { 555 verbose(8, "-- pass mismatch\n"); 556 continue; 557 } 558 } else if (FR_ISBLOCK(ipf->fl_flags)) { 559 if (a->ac_result != IPMR_BLOCK) { 560 verbose(8, "-- block mismatch\n"); 561 continue; 562 } 563 } else { /* Log only */ 564 if (a->ac_result != IPMR_LOG) { 565 verbose(8, "-- log mismatch\n"); 566 continue; 567 } 568 } 569 } 570 571 if ((a->ac_mflag & IPMAC_RULE) != 0) { 572 if (a->ac_rule != ipf->fl_rule) { 573 verbose(8, "-- rule mismatch\n"); 574 continue; 575 } 576 } 577 578 if ((a->ac_mflag & IPMAC_SRCIP) != 0) { 579 if ((ip->ip_src.s_addr & a->ac_smsk) != a->ac_sip) { 580 verbose(8, "-- srcip mismatch\n"); 581 continue; 582 } 583 } 584 585 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 586 if (ip->ip_p != IPPROTO_UDP && 587 ip->ip_p != IPPROTO_TCP) { 588 verbose(8, "-- port protocol mismatch\n"); 589 continue; 590 } 591 if (tcp->th_sport != a->ac_sport) { 592 verbose(8, "-- sport mismatch\n"); 593 continue; 594 } 595 } 596 597 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 598 if (a->ac_logtag != ipf->fl_logtag) { 599 verbose(8, "-- logtag %d != %d\n", 600 a->ac_logtag, ipf->fl_logtag); 601 continue; 602 } 603 } 604 605 if ((a->ac_mflag & IPMAC_NATTAG) != 0) { 606 if (strncmp(a->ac_nattag, ipf->fl_nattag.ipt_tag, 607 IPFTAG_LEN) != 0) { 608 verbose(8, "-- nattag mismatch\n"); 609 continue; 610 } 611 } 612 613 matched = 1; 614 verbose(8, "++ matched\n"); 615 616 /* 617 * It matched so now perform the saves 618 */ 619 for (d = a->ac_doing; d != NULL; d = d->ipmd_next) 620 (*d->ipmd_store)(d->ipmd_token, &msg); 621 } 622 623 return(matched); 624 } 625 626 627 static void 628 free_action(ipmon_action_t *a) 629 { 630 ipmon_doing_t *d; 631 632 while ((d = a->ac_doing) != NULL) { 633 a->ac_doing = d->ipmd_next; 634 (*d->ipmd_saver->ims_destroy)(d->ipmd_token); 635 free(d); 636 } 637 638 if (a->ac_iface != NULL) { 639 free(a->ac_iface); 640 a->ac_iface = NULL; 641 } 642 a->ac_next = NULL; 643 free(a); 644 } 645 646 647 int 648 load_config(char *file) 649 { 650 FILE *fp; 651 char *s; 652 653 unload_config(); 654 655 s = getenv("YYDEBUG"); 656 if (s != NULL) 657 yydebug = atoi(s); 658 else 659 yydebug = 0; 660 661 yylineNum = 1; 662 663 (void) yysettab(yywords); 664 665 fp = fopen(file, "r"); 666 if (!fp) { 667 perror("load_config:fopen:"); 668 return(-1); 669 } 670 yyin = fp; 671 while (!feof(fp)) 672 yyparse(); 673 fclose(fp); 674 return(0); 675 } 676 677 678 void 679 unload_config(void) 680 { 681 ipmon_saver_int_t *sav, **imsip; 682 ipmon_saver_t *is; 683 ipmon_action_t *a; 684 685 while ((a = alist) != NULL) { 686 alist = a->ac_next; 687 free_action(a); 688 } 689 690 /* 691 * Look for savers that have been added in dynamically from the 692 * configuration file. 693 */ 694 for (imsip = &saverlist; (sav = *imsip) != NULL; ) { 695 if (sav->imsi_handle == NULL) 696 imsip = &sav->imsi_next; 697 else { 698 dlclose(sav->imsi_handle); 699 700 *imsip = sav->imsi_next; 701 is = sav->imsi_stor; 702 free(sav); 703 704 free(is->ims_name); 705 free(is); 706 } 707 } 708 } 709 710 711 void 712 dump_config(void) 713 { 714 ipmon_action_t *a; 715 716 for (a = alist; a != NULL; a = a->ac_next) { 717 print_action(a); 718 719 printf("#\n"); 720 } 721 } 722 723 724 static void 725 print_action(ipmon_action_t *a) 726 { 727 ipmon_doing_t *d; 728 729 printf("match { "); 730 print_match(a); 731 printf("; }\n"); 732 printf("do {"); 733 for (d = a->ac_doing; d != NULL; d = d->ipmd_next) { 734 printf("%s", d->ipmd_saver->ims_name); 735 if (d->ipmd_saver->ims_print != NULL) { 736 printf("(\""); 737 (*d->ipmd_saver->ims_print)(d->ipmd_token); 738 printf("\")"); 739 } 740 printf(";"); 741 } 742 printf("};\n"); 743 } 744 745 746 void * 747 add_doing(ipmon_saver_t *saver) 748 { 749 ipmon_saver_int_t *it; 750 751 if (find_doing(saver->ims_name) == IPM_DOING) 752 return(NULL); 753 754 it = calloc(1, sizeof(*it)); 755 if (it == NULL) 756 return(NULL); 757 it->imsi_stor = saver; 758 it->imsi_next = saverlist; 759 saverlist = it; 760 return(it); 761 } 762 763 764 static int 765 find_doing(char *string) 766 { 767 ipmon_saver_int_t *it; 768 769 for (it = saverlist; it != NULL; it = it->imsi_next) { 770 if (!strcmp(it->imsi_stor->ims_name, string)) 771 return(IPM_DOING); 772 } 773 return(0); 774 } 775 776 777 static ipmon_doing_t * 778 build_doing(char *target, char *options) 779 { 780 ipmon_saver_int_t *it; 781 char *strarray[2]; 782 ipmon_doing_t *d, *d1; 783 ipmon_action_t *a; 784 ipmon_saver_t *save; 785 786 d = calloc(1, sizeof(*d)); 787 if (d == NULL) 788 return(NULL); 789 790 for (it = saverlist; it != NULL; it = it->imsi_next) { 791 if (!strcmp(it->imsi_stor->ims_name, target)) 792 break; 793 } 794 if (it == NULL) { 795 free(d); 796 return(NULL); 797 } 798 799 strarray[0] = options; 800 strarray[1] = NULL; 801 802 d->ipmd_token = (*it->imsi_stor->ims_parse)(strarray); 803 if (d->ipmd_token == NULL) { 804 free(d); 805 return(NULL); 806 } 807 808 save = it->imsi_stor; 809 d->ipmd_saver = save; 810 d->ipmd_store = it->imsi_stor->ims_store; 811 812 /* 813 * Look for duplicate do-things that need to be dup'd 814 */ 815 for (a = alist; a != NULL; a = a->ac_next) { 816 for (d1 = a->ac_doing; d1 != NULL; d1 = d1->ipmd_next) { 817 if (save != d1->ipmd_saver) 818 continue; 819 if (save->ims_match == NULL || save->ims_dup == NULL) 820 continue; 821 if ((*save->ims_match)(d->ipmd_token, d1->ipmd_token)) 822 continue; 823 824 (*d->ipmd_saver->ims_destroy)(d->ipmd_token); 825 d->ipmd_token = (*save->ims_dup)(d1->ipmd_token); 826 break; 827 } 828 } 829 830 return(d); 831 } 832 833 834 static void 835 print_match(ipmon_action_t *a) 836 { 837 char *coma = ""; 838 839 if ((a->ac_mflag & IPMAC_DIRECTION) != 0) { 840 printf("direction = "); 841 if (a->ac_direction == IPM_IN) 842 printf("in"); 843 else if (a->ac_direction == IPM_OUT) 844 printf("out"); 845 coma = ", "; 846 } 847 848 if ((a->ac_mflag & IPMAC_DSTIP) != 0) { 849 printf("%sdstip = ", coma); 850 printhostmask(AF_INET, &a->ac_dip, &a->ac_dmsk); 851 coma = ", "; 852 } 853 854 if ((a->ac_mflag & IPMAC_DSTPORT) != 0) { 855 printf("%sdstport = %hu", coma, ntohs(a->ac_dport)); 856 coma = ", "; 857 } 858 859 if ((a->ac_mflag & IPMAC_GROUP) != 0) { 860 char group[FR_GROUPLEN+1]; 861 862 strncpy(group, a->ac_group, FR_GROUPLEN); 863 group[FR_GROUPLEN] = '\0'; 864 printf("%sgroup = %s", coma, group); 865 coma = ", "; 866 } 867 868 if ((a->ac_mflag & IPMAC_INTERFACE) != 0) { 869 printf("%siface = %s", coma, a->ac_iface); 870 coma = ", "; 871 } 872 873 if ((a->ac_mflag & IPMAC_LOGTAG) != 0) { 874 printf("%slogtag = %u", coma, a->ac_logtag); 875 coma = ", "; 876 } 877 878 if ((a->ac_mflag & IPMAC_NATTAG) != 0) { 879 char tag[17]; 880 881 strncpy(tag, a->ac_nattag, 16); 882 tag[16] = '\0'; 883 printf("%snattag = %s", coma, tag); 884 coma = ", "; 885 } 886 887 if ((a->ac_mflag & IPMAC_PROTOCOL) != 0) { 888 printf("%sprotocol = %u", coma, a->ac_proto); 889 coma = ", "; 890 } 891 892 if ((a->ac_mflag & IPMAC_RESULT) != 0) { 893 printf("%sresult = ", coma); 894 switch (a->ac_result) 895 { 896 case IPMR_LOG : 897 printf("log"); 898 break; 899 case IPMR_PASS : 900 printf("pass"); 901 break; 902 case IPMR_BLOCK : 903 printf("block"); 904 break; 905 case IPMR_NOMATCH : 906 printf("nomatch"); 907 break; 908 } 909 coma = ", "; 910 } 911 912 if ((a->ac_mflag & IPMAC_RULE) != 0) { 913 printf("%srule = %u", coma, a->ac_rule); 914 coma = ", "; 915 } 916 917 if ((a->ac_mflag & IPMAC_EVERY) != 0) { 918 if (a->ac_packet > 1) { 919 printf("%severy %d packets", coma, a->ac_packet); 920 coma = ", "; 921 } else if (a->ac_packet == 1) { 922 printf("%severy packet", coma); 923 coma = ", "; 924 } 925 if (a->ac_second > 1) { 926 printf("%severy %d seconds", coma, a->ac_second); 927 coma = ", "; 928 } else if (a->ac_second == 1) { 929 printf("%severy second", coma); 930 coma = ", "; 931 } 932 } 933 934 if ((a->ac_mflag & IPMAC_SRCIP) != 0) { 935 printf("%ssrcip = ", coma); 936 printhostmask(AF_INET, &a->ac_sip, &a->ac_smsk); 937 coma = ", "; 938 } 939 940 if ((a->ac_mflag & IPMAC_SRCPORT) != 0) { 941 printf("%ssrcport = %hu", coma, ntohs(a->ac_sport)); 942 coma = ", "; 943 } 944 945 if ((a->ac_mflag & IPMAC_TYPE) != 0) { 946 printf("%stype = ", coma); 947 switch (a->ac_type) 948 { 949 case IPL_LOGIPF : 950 printf("ipf"); 951 break; 952 case IPL_LOGSTATE : 953 printf("state"); 954 break; 955 case IPL_LOGNAT : 956 printf("nat"); 957 break; 958 } 959 coma = ", "; 960 } 961 962 if ((a->ac_mflag & IPMAC_WITH) != 0) { 963 printf("%swith ", coma); 964 coma = ", "; 965 } 966 } 967 968 969 static int 970 install_saver(char *name, char *path) 971 { 972 ipmon_saver_int_t *isi; 973 ipmon_saver_t *is; 974 char nbuf[80]; 975 976 if (find_doing(name) == IPM_DOING) 977 return(-1); 978 979 isi = calloc(1, sizeof(*isi)); 980 if (isi == NULL) 981 return(-1); 982 983 is = calloc(1, sizeof(*is)); 984 if (is == NULL) 985 goto loaderror; 986 987 is->ims_name = name; 988 989 #ifdef RTLD_LAZY 990 isi->imsi_handle = dlopen(path, RTLD_LAZY); 991 #endif 992 #ifdef DL_LAZY 993 isi->imsi_handle = dlopen(path, DL_LAZY); 994 #endif 995 996 if (isi->imsi_handle == NULL) 997 goto loaderror; 998 999 snprintf(nbuf, sizeof(nbuf), "%sdup", name); 1000 is->ims_dup = (ims_dup_func_t)dlsym(isi->imsi_handle, nbuf); 1001 1002 snprintf(nbuf, sizeof(nbuf), "%sdestroy", name); 1003 is->ims_destroy = (ims_destroy_func_t)dlsym(isi->imsi_handle, nbuf); 1004 if (is->ims_destroy == NULL) 1005 goto loaderror; 1006 1007 snprintf(nbuf, sizeof(nbuf), "%smatch", name); 1008 is->ims_match = (ims_match_func_t)dlsym(isi->imsi_handle, nbuf); 1009 1010 snprintf(nbuf, sizeof(nbuf), "%sparse", name); 1011 is->ims_parse = (ims_parse_func_t)dlsym(isi->imsi_handle, nbuf); 1012 if (is->ims_parse == NULL) 1013 goto loaderror; 1014 1015 snprintf(nbuf, sizeof(nbuf), "%sprint", name); 1016 is->ims_print = (ims_print_func_t)dlsym(isi->imsi_handle, nbuf); 1017 if (is->ims_print == NULL) 1018 goto loaderror; 1019 1020 snprintf(nbuf, sizeof(nbuf), "%sstore", name); 1021 is->ims_store = (ims_store_func_t)dlsym(isi->imsi_handle, nbuf); 1022 if (is->ims_store == NULL) 1023 goto loaderror; 1024 1025 isi->imsi_stor = is; 1026 isi->imsi_next = saverlist; 1027 saverlist = isi; 1028 1029 return(0); 1030 1031 loaderror: 1032 if (isi->imsi_handle != NULL) 1033 dlclose(isi->imsi_handle); 1034 free(isi); 1035 if (is != NULL) 1036 free(is); 1037 return(-1); 1038 } 1039