1 2 /* 3 * Copyright (C) 2012 by Darren Reed. 4 * 5 * See the IPFILTER.LICENCE file for details on licencing. 6 */ 7 #include "ipf.h" 8 #include "ipmon.h" 9 #include <sys/ioctl.h> 10 #include <sys/stat.h> 11 #include <syslog.h> 12 #include <ctype.h> 13 #include <fcntl.h> 14 #include <signal.h> 15 16 17 18 #define STRERROR(x) strerror(x) 19 20 extern int optind; 21 extern char *optarg; 22 23 extern ipmon_saver_t executesaver; 24 extern ipmon_saver_t filesaver; 25 extern ipmon_saver_t nothingsaver; 26 extern ipmon_saver_t snmpv1saver; 27 extern ipmon_saver_t snmpv2saver; 28 extern ipmon_saver_t syslogsaver; 29 30 31 struct flags { 32 int value; 33 char flag; 34 }; 35 36 typedef struct logsource { 37 int fd; 38 int logtype; 39 char *file; 40 int regular; 41 size_t size; 42 } logsource_t; 43 44 typedef struct config { 45 int opts; 46 int maxfd; 47 logsource_t logsrc[3]; 48 fd_set fdmr; 49 FILE *blog; 50 char *bfile; 51 FILE *log; 52 char *file; 53 char *cfile; 54 } config_t; 55 56 typedef struct icmp_subtype { 57 int ist_val; 58 char *ist_name; 59 } icmp_subtype_t; 60 61 typedef struct icmp_type { 62 int it_val; 63 struct icmp_subtype *it_subtable; 64 size_t it_stsize; 65 char *it_name; 66 } icmp_type_t; 67 68 69 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) 70 71 72 struct flags tcpfl[] = { 73 { TH_ACK, 'A' }, 74 { TH_RST, 'R' }, 75 { TH_SYN, 'S' }, 76 { TH_FIN, 'F' }, 77 { TH_URG, 'U' }, 78 { TH_PUSH,'P' }, 79 { TH_ECN, 'E' }, 80 { TH_CWR, 'W' }, 81 { TH_AE, 'e' }, 82 { 0, '\0' } 83 }; 84 85 char *reasons[] = { 86 "filter-rule", 87 "log-or-block_1", 88 "pps-rate", 89 "jumbogram", 90 "makefrip-fail", 91 "state_add-fail", 92 "updateipid-fail", 93 "log-or-block_2", 94 "decap-fail", 95 "auth_new-fail", 96 "auth_captured", 97 "coalesce-fail", 98 "pullup-fail", 99 "auth-feedback", 100 "bad-frag", 101 "natv4_out-fail", 102 "natv4_in-fail", 103 "natv6_out-fail", 104 "natv6_in-fail", 105 }; 106 107 #if SOLARIS 108 static char *pidfile = "/etc/opt/ipf/ipmon.pid"; 109 #else 110 static char *pidfile = "/var/run/ipmon.pid"; 111 #endif 112 113 static char line[2048]; 114 static int donehup = 0; 115 static void usage(char *); 116 static void handlehup(int); 117 static void flushlogs(char *, FILE *); 118 static void print_log(config_t *, logsource_t *, char *, int); 119 static void print_ipflog(config_t *, char *, int); 120 static void print_natlog(config_t *, char *, int); 121 static void print_statelog(config_t *, char *, int); 122 static int read_log(int, int *, char *, int); 123 static void write_pid(char *); 124 static char *icmpname(u_int, u_int); 125 static char *icmpname6(u_int, u_int); 126 static icmp_type_t *find_icmptype(int, icmp_type_t *, size_t); 127 static icmp_subtype_t *find_icmpsubtype(int, icmp_subtype_t *, size_t); 128 static struct tm *get_tm(time_t); 129 130 char *portlocalname(int, char *, u_int); 131 int main(int, char *[]); 132 133 static void logopts(int, char *); 134 static void init_tabs(void); 135 static char *getlocalproto(u_int); 136 static void openlogs(config_t *conf); 137 static int read_loginfo(config_t *conf); 138 static void initconfig(config_t *conf); 139 140 static char **protocols = NULL; 141 static char **udp_ports = NULL; 142 static char **tcp_ports = NULL; 143 144 145 #define HOSTNAMEV4(b) hostname(AF_INET, (u_32_t *)&(b)) 146 147 #ifndef LOGFAC 148 #define LOGFAC LOG_LOCAL0 149 #endif 150 int logfac = LOGFAC; 151 int ipmonopts = 0; 152 int opts = OPT_NORESOLVE; 153 int use_inet6 = 0; 154 155 156 static icmp_subtype_t icmpunreachnames[] = { 157 { ICMP_UNREACH_NET, "net" }, 158 { ICMP_UNREACH_HOST, "host" }, 159 { ICMP_UNREACH_PROTOCOL, "protocol" }, 160 { ICMP_UNREACH_PORT, "port" }, 161 { ICMP_UNREACH_NEEDFRAG, "needfrag" }, 162 { ICMP_UNREACH_SRCFAIL, "srcfail" }, 163 { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, 164 { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, 165 { ICMP_UNREACH_NET, "isolated" }, 166 { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, 167 { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, 168 { ICMP_UNREACH_TOSNET, "tosnet" }, 169 { ICMP_UNREACH_TOSHOST, "toshost" }, 170 { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, 171 { -2, NULL } 172 }; 173 174 static icmp_subtype_t redirectnames[] = { 175 { ICMP_REDIRECT_NET, "net" }, 176 { ICMP_REDIRECT_HOST, "host" }, 177 { ICMP_REDIRECT_TOSNET, "tosnet" }, 178 { ICMP_REDIRECT_TOSHOST, "toshost" }, 179 { -2, NULL } 180 }; 181 182 static icmp_subtype_t timxceednames[] = { 183 { ICMP_TIMXCEED_INTRANS, "transit" }, 184 { ICMP_TIMXCEED_REASS, "reassem" }, 185 { -2, NULL } 186 }; 187 188 static icmp_subtype_t paramnames[] = { 189 { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, 190 { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, 191 { ICMP_PARAMPROB_LENGTH, "length" }, 192 { -2, NULL } 193 }; 194 195 static icmp_type_t icmptypes4[] = { 196 { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, 197 { -1, NULL, 0, NULL }, 198 { -1, NULL, 0, NULL }, 199 { ICMP_UNREACH, icmpunreachnames, 200 IST_SZ(icmpunreachnames),"unreach" }, 201 { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, 202 { ICMP_REDIRECT, redirectnames, 203 IST_SZ(redirectnames), "redirect" }, 204 { -1, NULL, 0, NULL }, 205 { -1, NULL, 0, NULL }, 206 { ICMP_ECHO, NULL, 0, "echo" }, 207 { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, 208 { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, 209 { ICMP_TIMXCEED, timxceednames, 210 IST_SZ(timxceednames), "timxceed" }, 211 { ICMP_PARAMPROB, paramnames, 212 IST_SZ(paramnames), "paramprob" }, 213 { ICMP_TSTAMP, NULL, 0, "timestamp" }, 214 { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, 215 { ICMP_IREQ, NULL, 0, "inforeq" }, 216 { ICMP_IREQREPLY, NULL, 0, "inforeply" }, 217 { ICMP_MASKREQ, NULL, 0, "maskreq" }, 218 { ICMP_MASKREPLY, NULL, 0, "maskreply" }, 219 { -2, NULL, 0, NULL } 220 }; 221 222 static icmp_subtype_t icmpredirect6[] = { 223 { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, 224 { ICMP6_DST_UNREACH_ADMIN, "admin" }, 225 { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, 226 { ICMP6_DST_UNREACH_ADDR, "address" }, 227 { ICMP6_DST_UNREACH_NOPORT, "noport" }, 228 { -2, NULL } 229 }; 230 231 static icmp_subtype_t icmptimexceed6[] = { 232 { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, 233 { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, 234 { -2, NULL } 235 }; 236 237 static icmp_subtype_t icmpparamprob6[] = { 238 { ICMP6_PARAMPROB_HEADER, "header" }, 239 { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, 240 { ICMP6_PARAMPROB_OPTION, "option" }, 241 { -2, NULL } 242 }; 243 244 static icmp_subtype_t icmpquerysubject6[] = { 245 { ICMP6_NI_SUBJ_IPV6, "ipv6" }, 246 { ICMP6_NI_SUBJ_FQDN, "fqdn" }, 247 { ICMP6_NI_SUBJ_IPV4, "ipv4" }, 248 { -2, NULL }, 249 }; 250 251 static icmp_subtype_t icmpnodeinfo6[] = { 252 { ICMP6_NI_SUCCESS, "success" }, 253 { ICMP6_NI_REFUSED, "refused" }, 254 { ICMP6_NI_UNKNOWN, "unknown" }, 255 { -2, NULL } 256 }; 257 258 static icmp_subtype_t icmprenumber6[] = { 259 { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, 260 { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, 261 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, 262 { -2, NULL } 263 }; 264 265 static icmp_type_t icmptypes6[] = { 266 { 0, NULL, 0, NULL }, 267 { ICMP6_DST_UNREACH, icmpredirect6, 268 IST_SZ(icmpredirect6), "unreach" }, 269 { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, 270 { ICMP6_TIME_EXCEEDED, icmptimexceed6, 271 IST_SZ(icmptimexceed6), "timxceed" }, 272 { ICMP6_PARAM_PROB, icmpparamprob6, 273 IST_SZ(icmpparamprob6), "paramprob" }, 274 { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, 275 { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, 276 { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, 277 IST_SZ(icmpquerysubject6), "groupmemberquery" }, 278 { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, 279 { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, 280 { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, 281 { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, 282 { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, 283 { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, 284 { ND_REDIRECT, NULL, 0, "redirect" }, 285 { ICMP6_ROUTER_RENUMBERING, icmprenumber6, 286 IST_SZ(icmprenumber6), "routerrenumber" }, 287 { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, 288 { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, 289 { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, 290 { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, 291 { ICMP6_NI_QUERY, icmpnodeinfo6, 292 IST_SZ(icmpnodeinfo6), "nodeinforequest" }, 293 { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, 294 { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, 295 { MLD6_MTRACE, NULL, 0, "mtracerequest" }, 296 { -2, NULL, 0, NULL } 297 }; 298 299 static icmp_subtype_t * 300 find_icmpsubtype(int type, icmp_subtype_t *table, size_t tablesz) 301 { 302 icmp_subtype_t *ist; 303 304 if (tablesz < 2) 305 return (NULL); 306 307 if ((type < 0) || (type > table[tablesz - 2].ist_val)) 308 return (NULL); 309 310 if (table[type].ist_val == type) 311 return (table + type); 312 313 for (ist = table; ist->ist_val != -2; ist++) 314 if (ist->ist_val == type) 315 return (ist); 316 return (NULL); 317 } 318 319 320 static icmp_type_t * 321 find_icmptype(int type, icmp_type_t *table, size_t tablesz) 322 { 323 icmp_type_t *it; 324 325 if (tablesz < 2) 326 return (NULL); 327 328 if ((type < 0) || (type > table[tablesz - 2].it_val)) 329 return (NULL); 330 331 if (table[type].it_val == type) 332 return (table + type); 333 334 for (it = table; it->it_val != -2; it++) 335 if (it->it_val == type) 336 return (it); 337 return (NULL); 338 } 339 340 341 static void 342 handlehup(int sig) 343 { 344 signal(SIGHUP, handlehup); 345 donehup = 1; 346 } 347 348 349 static void 350 init_tabs(void) 351 { 352 struct protoent *p; 353 struct servent *s; 354 char *name, **tab; 355 int port, i; 356 357 if (protocols != NULL) { 358 for (i = 0; i < 256; i++) 359 if (protocols[i] != NULL) { 360 free(protocols[i]); 361 protocols[i] = NULL; 362 } 363 free(protocols); 364 protocols = NULL; 365 } 366 protocols = (char **)malloc(256 * sizeof(*protocols)); 367 if (protocols != NULL) { 368 bzero((char *)protocols, 256 * sizeof(*protocols)); 369 370 setprotoent(1); 371 while ((p = getprotoent()) != NULL) 372 if (p->p_proto >= 0 && p->p_proto <= 255 && 373 p->p_name != NULL && protocols[p->p_proto] == NULL) 374 protocols[p->p_proto] = strdup(p->p_name); 375 endprotoent(); 376 if (protocols[0]) 377 free(protocols[0]); 378 protocols[0] = strdup("ip"); 379 } 380 381 if (udp_ports != NULL) { 382 for (i = 0; i < 65536; i++) 383 if (udp_ports[i] != NULL) { 384 free(udp_ports[i]); 385 udp_ports[i] = NULL; 386 } 387 free(udp_ports); 388 udp_ports = NULL; 389 } 390 udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 391 if (udp_ports != NULL) 392 bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 393 394 if (tcp_ports != NULL) { 395 for (i = 0; i < 65536; i++) 396 if (tcp_ports[i] != NULL) { 397 free(tcp_ports[i]); 398 tcp_ports[i] = NULL; 399 } 400 free(tcp_ports); 401 tcp_ports = NULL; 402 } 403 tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 404 if (tcp_ports != NULL) 405 bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 406 407 setservent(1); 408 while ((s = getservent()) != NULL) { 409 if (s->s_proto == NULL) 410 continue; 411 else if (!strcmp(s->s_proto, "tcp")) { 412 port = ntohs(s->s_port); 413 name = s->s_name; 414 tab = tcp_ports; 415 } else if (!strcmp(s->s_proto, "udp")) { 416 port = ntohs(s->s_port); 417 name = s->s_name; 418 tab = udp_ports; 419 } else 420 continue; 421 if ((port < 0 || port > 65535) || (name == NULL)) 422 continue; 423 if (tab != NULL) 424 tab[port] = strdup(name); 425 } 426 endservent(); 427 } 428 429 430 static char * 431 getlocalproto(u_int p) 432 { 433 static char pnum[4]; 434 char *s; 435 436 p &= 0xff; 437 s = protocols ? protocols[p] : NULL; 438 if (s == NULL) { 439 sprintf(pnum, "%u", p); 440 s = pnum; 441 } 442 return (s); 443 } 444 445 446 static int 447 read_log(int fd, int *lenp, char *buf, int bufsize) 448 { 449 int nr; 450 451 if (bufsize > IPFILTER_LOGSIZE) 452 bufsize = IPFILTER_LOGSIZE; 453 454 nr = read(fd, buf, bufsize); 455 if (!nr) 456 return (2); 457 if ((nr < 0) && (errno != EINTR)) 458 return (-1); 459 *lenp = nr; 460 return (0); 461 } 462 463 464 char * 465 portlocalname(int res, char *proto, u_int port) 466 { 467 static char pname[8]; 468 char *s; 469 470 port = ntohs(port); 471 port &= 0xffff; 472 sprintf(pname, "%u", port); 473 if (!res || (ipmonopts & IPMON_PORTNUM)) 474 return (pname); 475 s = NULL; 476 if (!strcmp(proto, "tcp")) 477 s = tcp_ports[port]; 478 else if (!strcmp(proto, "udp")) 479 s = udp_ports[port]; 480 if (s == NULL) 481 s = pname; 482 return (s); 483 } 484 485 486 static char * 487 icmpname(u_int type, u_int code) 488 { 489 static char name[80]; 490 icmp_subtype_t *ist; 491 icmp_type_t *it; 492 char *s; 493 494 s = NULL; 495 it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); 496 if (it != NULL) 497 s = it->it_name; 498 499 if (s == NULL) 500 sprintf(name, "icmptype(%d)/", type); 501 else 502 sprintf(name, "%s/", s); 503 504 ist = NULL; 505 if (it != NULL && it->it_subtable != NULL) 506 ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 507 508 if (ist != NULL && ist->ist_name != NULL) 509 strcat(name, ist->ist_name); 510 else 511 sprintf(name + strlen(name), "%d", code); 512 513 return (name); 514 } 515 516 static char * 517 icmpname6(u_int type, u_int code) 518 { 519 static char name[80]; 520 icmp_subtype_t *ist; 521 icmp_type_t *it; 522 char *s; 523 524 s = NULL; 525 it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 526 if (it != NULL) 527 s = it->it_name; 528 529 if (s == NULL) 530 sprintf(name, "icmpv6type(%d)/", type); 531 else 532 sprintf(name, "%s/", s); 533 534 ist = NULL; 535 if (it != NULL && it->it_subtable != NULL) 536 ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 537 538 if (ist != NULL && ist->ist_name != NULL) 539 strcat(name, ist->ist_name); 540 else 541 sprintf(name + strlen(name), "%d", code); 542 543 return (name); 544 } 545 546 547 void 548 dumphex(FILE *log, int dopts, char *buf, int len) 549 { 550 char hline[80]; 551 int i, j, k; 552 u_char *s = (u_char *)buf, *t = (u_char *)hline; 553 554 if (buf == NULL || len == 0) 555 return; 556 557 *hline = '\0'; 558 559 for (i = len, j = 0; i; i--, j++, s++) { 560 if (j && !(j & 0xf)) { 561 *t++ = '\n'; 562 *t = '\0'; 563 if ((dopts & IPMON_SYSLOG)) 564 syslog(LOG_INFO, "%s", hline); 565 else if (log != NULL) 566 fputs(hline, log); 567 t = (u_char *)hline; 568 *t = '\0'; 569 } 570 sprintf((char *)t, "%02x", *s & 0xff); 571 t += 2; 572 if (!((j + 1) & 0xf)) { 573 s -= 15; 574 sprintf((char *)t, " "); 575 t += 8; 576 for (k = 16; k; k--, s++) 577 *t++ = (isprint(*s) ? *s : '.'); 578 s--; 579 } 580 581 if ((j + 1) & 0xf) 582 *t++ = ' '; 583 } 584 585 if (j & 0xf) { 586 for (k = 16 - (j & 0xf); k; k--) { 587 *t++ = ' '; 588 *t++ = ' '; 589 *t++ = ' '; 590 } 591 sprintf((char *)t, " "); 592 t += 7; 593 s -= j & 0xf; 594 for (k = j & 0xf; k; k--, s++) 595 *t++ = (isprint(*s) ? *s : '.'); 596 *t++ = '\n'; 597 *t = '\0'; 598 } 599 if ((dopts & IPMON_SYSLOG) != 0) 600 syslog(LOG_INFO, "%s", hline); 601 else if (log != NULL) { 602 fputs(hline, log); 603 fflush(log); 604 } 605 } 606 607 608 static struct tm * 609 get_tm(time_t sec) 610 { 611 struct tm *tm; 612 time_t t; 613 614 t = sec; 615 tm = localtime(&t); 616 return (tm); 617 } 618 619 static void 620 print_natlog(config_t *conf, char *buf, int blen) 621 { 622 static u_32_t seqnum = 0; 623 int res, i, len, family; 624 struct natlog *nl; 625 struct tm *tm; 626 iplog_t *ipl; 627 char *proto; 628 int simple; 629 char *t; 630 631 t = line; 632 simple = 0; 633 ipl = (iplog_t *)buf; 634 if (ipl->ipl_seqnum != seqnum) { 635 if ((ipmonopts & IPMON_SYSLOG) != 0) { 636 syslog(LOG_WARNING, 637 "missed %u NAT log entries: %u %u", 638 ipl->ipl_seqnum - seqnum, seqnum, 639 ipl->ipl_seqnum); 640 } else { 641 (void) fprintf(conf->log, 642 "missed %u NAT log entries: %u %u\n", 643 ipl->ipl_seqnum - seqnum, seqnum, 644 ipl->ipl_seqnum); 645 } 646 } 647 seqnum = ipl->ipl_seqnum + ipl->ipl_count; 648 649 nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 650 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 651 tm = get_tm(ipl->ipl_sec); 652 len = sizeof(line); 653 654 if (!(ipmonopts & IPMON_SYSLOG)) { 655 (void) strftime(t, len, "%d/%m/%Y ", tm); 656 i = strlen(t); 657 len -= i; 658 t += i; 659 } 660 (void) strftime(t, len, "%T", tm); 661 t += strlen(t); 662 sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); 663 t += strlen(t); 664 665 switch (nl->nl_action) 666 { 667 case NL_NEW : 668 strcpy(t, "NAT:NEW"); 669 break; 670 671 case NL_FLUSH : 672 strcpy(t, "NAT:FLUSH"); 673 break; 674 675 case NL_CLONE : 676 strcpy(t, "NAT:CLONE"); 677 break; 678 679 case NL_EXPIRE : 680 strcpy(t, "NAT:EXPIRE"); 681 break; 682 683 case NL_DESTROY : 684 strcpy(t, "NAT:DESTROY"); 685 break; 686 687 case NL_PURGE : 688 strcpy(t, "NAT:PURGE"); 689 break; 690 691 default : 692 sprintf(t, "NAT:Action(%d)", nl->nl_action); 693 break; 694 } 695 t += strlen(t); 696 697 698 switch (nl->nl_type) 699 { 700 case NAT_MAP : 701 strcpy(t, "-MAP "); 702 simple = 1; 703 break; 704 705 case NAT_REDIRECT : 706 strcpy(t, "-RDR "); 707 simple = 1; 708 break; 709 710 case NAT_BIMAP : 711 strcpy(t, "-BIMAP "); 712 simple = 1; 713 break; 714 715 case NAT_MAPBLK : 716 strcpy(t, "-MAPBLOCK "); 717 simple = 1; 718 break; 719 720 case NAT_REWRITE|NAT_MAP : 721 strcpy(t, "-RWR_MAP "); 722 break; 723 724 case NAT_REWRITE|NAT_REDIRECT : 725 strcpy(t, "-RWR_RDR "); 726 break; 727 728 case NAT_ENCAP|NAT_MAP : 729 strcpy(t, "-ENC_MAP "); 730 break; 731 732 case NAT_ENCAP|NAT_REDIRECT : 733 strcpy(t, "-ENC_RDR "); 734 break; 735 736 case NAT_DIVERTUDP|NAT_MAP : 737 strcpy(t, "-DIV_MAP "); 738 break; 739 740 case NAT_DIVERTUDP|NAT_REDIRECT : 741 strcpy(t, "-DIV_RDR "); 742 break; 743 744 default : 745 sprintf(t, "-Type(%d) ", nl->nl_type); 746 break; 747 } 748 t += strlen(t); 749 750 proto = getlocalproto(nl->nl_p[0]); 751 752 family = vtof(nl->nl_v[0]); 753 754 if (simple == 1) { 755 sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6), 756 portlocalname(res, proto, (u_int)nl->nl_osrcport)); 757 t += strlen(t); 758 sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 759 portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 760 t += strlen(t); 761 sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6), 762 portlocalname(res, proto, (u_int)nl->nl_odstport)); 763 } else { 764 sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6), 765 portlocalname(res, proto, (u_int)nl->nl_osrcport)); 766 t += strlen(t); 767 sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6), 768 portlocalname(res, proto, (u_int)nl->nl_odstport)); 769 t += strlen(t); 770 sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 771 portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 772 t += strlen(t); 773 sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6), 774 portlocalname(res, proto, (u_int)nl->nl_ndstport)); 775 } 776 t += strlen(t); 777 778 strcpy(t, getlocalproto(nl->nl_p[0])); 779 t += strlen(t); 780 781 if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { 782 #ifdef USE_QUAD_T 783 # ifdef PRId64 784 sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" 785 PRId64, 786 # else 787 sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 788 # endif 789 #else 790 sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 791 #endif 792 nl->nl_pkts[0], nl->nl_pkts[1], 793 nl->nl_bytes[0], nl->nl_bytes[1]); 794 t += strlen(t); 795 } 796 797 *t++ = '\n'; 798 *t++ = '\0'; 799 if (ipmonopts & IPMON_SYSLOG) 800 syslog(LOG_INFO, "%s", line); 801 else if (conf->log != NULL) 802 (void) fprintf(conf->log, "%s", line); 803 } 804 805 806 static void 807 print_statelog(config_t *conf, char *buf, int blen) 808 { 809 static u_32_t seqnum = 0; 810 int res, i, len, family; 811 struct ipslog *sl; 812 char *t, *proto; 813 struct tm *tm; 814 iplog_t *ipl; 815 816 t = line; 817 ipl = (iplog_t *)buf; 818 if (ipl->ipl_seqnum != seqnum) { 819 if ((ipmonopts & IPMON_SYSLOG) != 0) { 820 syslog(LOG_WARNING, 821 "missed %u state log entries: %u %u", 822 ipl->ipl_seqnum - seqnum, seqnum, 823 ipl->ipl_seqnum); 824 } else { 825 (void) fprintf(conf->log, 826 "missed %u state log entries: %u %u\n", 827 ipl->ipl_seqnum - seqnum, seqnum, 828 ipl->ipl_seqnum); 829 } 830 } 831 seqnum = ipl->ipl_seqnum + ipl->ipl_count; 832 833 sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 834 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 835 tm = get_tm(ipl->ipl_sec); 836 len = sizeof(line); 837 if (!(ipmonopts & IPMON_SYSLOG)) { 838 (void) strftime(t, len, "%d/%m/%Y ", tm); 839 i = strlen(t); 840 len -= i; 841 t += i; 842 } 843 (void) strftime(t, len, "%T", tm); 844 t += strlen(t); 845 sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 846 t += strlen(t); 847 848 family = vtof(sl->isl_v); 849 850 switch (sl->isl_type) 851 { 852 case ISL_NEW : 853 strcpy(t, "STATE:NEW "); 854 break; 855 856 case ISL_CLONE : 857 strcpy(t, "STATE:CLONED "); 858 break; 859 860 case ISL_EXPIRE : 861 if ((sl->isl_p == IPPROTO_TCP) && 862 (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 863 sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 864 strcpy(t, "STATE:CLOSE "); 865 else 866 strcpy(t, "STATE:EXPIRE "); 867 break; 868 869 case ISL_FLUSH : 870 strcpy(t, "STATE:FLUSH "); 871 break; 872 873 case ISL_INTERMEDIATE : 874 strcpy(t, "STATE:INTERMEDIATE "); 875 break; 876 877 case ISL_REMOVE : 878 strcpy(t, "STATE:REMOVE "); 879 break; 880 881 case ISL_KILLED : 882 strcpy(t, "STATE:KILLED "); 883 break; 884 885 case ISL_UNLOAD : 886 strcpy(t, "STATE:UNLOAD "); 887 break; 888 889 default : 890 sprintf(t, "Type: %d ", sl->isl_type); 891 break; 892 } 893 t += strlen(t); 894 895 proto = getlocalproto(sl->isl_p); 896 897 if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 898 sprintf(t, "%s,%s -> ", 899 hostname(family, (u_32_t *)&sl->isl_src), 900 portlocalname(res, proto, (u_int)sl->isl_sport)); 901 t += strlen(t); 902 sprintf(t, "%s,%s PR %s", 903 hostname(family, (u_32_t *)&sl->isl_dst), 904 portlocalname(res, proto, (u_int)sl->isl_dport), proto); 905 } else if (sl->isl_p == IPPROTO_ICMP) { 906 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 907 t += strlen(t); 908 sprintf(t, "%s PR icmp %d", 909 hostname(family, (u_32_t *)&sl->isl_dst), 910 sl->isl_itype); 911 } else if (sl->isl_p == IPPROTO_ICMPV6) { 912 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 913 t += strlen(t); 914 sprintf(t, "%s PR icmpv6 %d", 915 hostname(family, (u_32_t *)&sl->isl_dst), 916 sl->isl_itype); 917 } else { 918 sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 919 t += strlen(t); 920 sprintf(t, "%s PR %s", 921 hostname(family, (u_32_t *)&sl->isl_dst), proto); 922 } 923 t += strlen(t); 924 if (sl->isl_tag != FR_NOLOGTAG) { 925 sprintf(t, " tag %u", sl->isl_tag); 926 t += strlen(t); 927 } 928 if (sl->isl_type != ISL_NEW) { 929 sprintf(t, 930 #ifdef USE_QUAD_T 931 #ifdef PRId64 932 " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 933 " Pkts out %" PRId64 " Bytes out %" PRId64 934 " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 935 " Pkts out %" PRId64 " Bytes out %" PRId64, 936 #else 937 " Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd", 938 #endif /* PRId64 */ 939 #else 940 " Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld", 941 #endif 942 sl->isl_pkts[0], sl->isl_bytes[0], 943 sl->isl_pkts[1], sl->isl_bytes[1], 944 sl->isl_pkts[2], sl->isl_bytes[2], 945 sl->isl_pkts[3], sl->isl_bytes[3]); 946 947 t += strlen(t); 948 } 949 950 *t++ = '\n'; 951 *t++ = '\0'; 952 if (ipmonopts & IPMON_SYSLOG) 953 syslog(LOG_INFO, "%s", line); 954 else if (conf->log != NULL) 955 (void) fprintf(conf->log, "%s", line); 956 } 957 958 959 static void 960 print_log(config_t *conf, logsource_t *log, char *buf, int blen) 961 { 962 char *bp, *bpo; 963 iplog_t *ipl; 964 int psize; 965 966 bp = NULL; 967 bpo = NULL; 968 969 while (blen > 0) { 970 ipl = (iplog_t *)buf; 971 if ((u_long)ipl & (sizeof(long)-1)) { 972 if (bp) 973 bpo = bp; 974 bp = (char *)malloc(blen); 975 bcopy((char *)ipl, bp, blen); 976 if (bpo) { 977 free(bpo); 978 bpo = NULL; 979 } 980 buf = bp; 981 continue; 982 } 983 984 psize = ipl->ipl_dsize; 985 if (psize > blen) 986 break; 987 988 if (conf->blog != NULL) { 989 fwrite(buf, psize, 1, conf->blog); 990 fflush(conf->blog); 991 } 992 993 if (log->logtype == IPL_LOGIPF) { 994 if (ipl->ipl_magic == IPL_MAGIC) 995 print_ipflog(conf, buf, psize); 996 997 } else if (log->logtype == IPL_LOGNAT) { 998 if (ipl->ipl_magic == IPL_MAGIC_NAT) 999 print_natlog(conf, buf, psize); 1000 1001 } else if (log->logtype == IPL_LOGSTATE) { 1002 if (ipl->ipl_magic == IPL_MAGIC_STATE) 1003 print_statelog(conf, buf, psize); 1004 } 1005 1006 blen -= psize; 1007 buf += psize; 1008 } 1009 if (bp) 1010 free(bp); 1011 return; 1012 } 1013 1014 1015 static void 1016 print_ipflog(config_t *conf, char *buf, int blen) 1017 { 1018 static u_32_t seqnum = 0; 1019 int i, f, lvl, res, len, off, plen, ipoff, defaction; 1020 struct icmp *icmp; 1021 struct icmp *ic; 1022 char *t, *proto; 1023 ip_t *ipc, *ip; 1024 struct tm *tm; 1025 u_32_t *s, *d; 1026 u_short hl, p; 1027 ipflog_t *ipf; 1028 iplog_t *ipl; 1029 tcphdr_t *tp; 1030 #ifdef USE_INET6 1031 struct ip6_ext *ehp; 1032 u_short ehl; 1033 ip6_t *ip6; 1034 int go; 1035 #endif 1036 1037 ipl = (iplog_t *)buf; 1038 if (ipl->ipl_seqnum != seqnum) { 1039 if ((ipmonopts & IPMON_SYSLOG) != 0) { 1040 syslog(LOG_WARNING, 1041 "missed %u ipf log entries: %u %u", 1042 ipl->ipl_seqnum - seqnum, seqnum, 1043 ipl->ipl_seqnum); 1044 } else { 1045 (void) fprintf(conf->log, 1046 "missed %u ipf log entries: %u %u\n", 1047 ipl->ipl_seqnum - seqnum, seqnum, 1048 ipl->ipl_seqnum); 1049 } 1050 } 1051 seqnum = ipl->ipl_seqnum + ipl->ipl_count; 1052 1053 ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 1054 ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 1055 f = ipf->fl_family; 1056 res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 1057 t = line; 1058 *t = '\0'; 1059 tm = get_tm(ipl->ipl_sec); 1060 1061 len = sizeof(line); 1062 if (!(ipmonopts & IPMON_SYSLOG)) { 1063 (void) strftime(t, len, "%d/%m/%Y ", tm); 1064 i = strlen(t); 1065 len -= i; 1066 t += i; 1067 } 1068 (void) strftime(t, len, "%T", tm); 1069 t += strlen(t); 1070 sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 1071 t += strlen(t); 1072 if (ipl->ipl_count > 1) { 1073 sprintf(t, "%dx ", ipl->ipl_count); 1074 t += strlen(t); 1075 } 1076 { 1077 char ifname[sizeof(ipf->fl_ifname) + 1]; 1078 1079 strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 1080 ifname[sizeof(ipf->fl_ifname)] = '\0'; 1081 sprintf(t, "%s", ifname); 1082 t += strlen(t); 1083 # if SOLARIS 1084 if (ISALPHA(*(t - 1))) { 1085 sprintf(t, "%d", ipf->fl_unit); 1086 t += strlen(t); 1087 } 1088 # endif 1089 } 1090 if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) 1091 strcat(t, " @-1:"); 1092 else if (ipf->fl_group[0] == '\0') 1093 (void) strcpy(t, " @0:"); 1094 else 1095 sprintf(t, " @%s:", ipf->fl_group); 1096 t += strlen(t); 1097 if (ipf->fl_rule == 0xffffffff) 1098 strcat(t, "-1 "); 1099 else 1100 sprintf(t, "%u ", ipf->fl_rule + 1); 1101 t += strlen(t); 1102 1103 lvl = LOG_NOTICE; 1104 1105 if (ipf->fl_lflags & FI_SHORT) { 1106 *t++ = 'S'; 1107 lvl = LOG_ERR; 1108 } 1109 1110 if (FR_ISPASS(ipf->fl_flags)) { 1111 if (ipf->fl_flags & FR_LOGP) 1112 *t++ = 'p'; 1113 else 1114 *t++ = 'P'; 1115 } else if (FR_ISBLOCK(ipf->fl_flags)) { 1116 if (ipf->fl_flags & FR_LOGB) 1117 *t++ = 'b'; 1118 else 1119 *t++ = 'B'; 1120 lvl = LOG_WARNING; 1121 } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 1122 *t++ = 'L'; 1123 lvl = LOG_INFO; 1124 } else if (ipf->fl_flags & FF_LOGNOMATCH) { 1125 *t++ = 'n'; 1126 } else { 1127 *t++ = '?'; 1128 lvl = LOG_EMERG; 1129 } 1130 if (ipf->fl_loglevel != 0xffff) 1131 lvl = ipf->fl_loglevel; 1132 *t++ = ' '; 1133 *t = '\0'; 1134 1135 if (f == AF_INET) { 1136 hl = IP_HL(ip) << 2; 1137 ipoff = ntohs(ip->ip_off); 1138 off = ipoff & IP_OFFMASK; 1139 p = (u_short)ip->ip_p; 1140 s = (u_32_t *)&ip->ip_src; 1141 d = (u_32_t *)&ip->ip_dst; 1142 plen = ntohs(ip->ip_len); 1143 } else 1144 #ifdef USE_INET6 1145 if (f == AF_INET6) { 1146 off = 0; 1147 ipoff = 0; 1148 hl = sizeof(ip6_t); 1149 ip6 = (ip6_t *)ip; 1150 p = (u_short)ip6->ip6_nxt; 1151 s = (u_32_t *)&ip6->ip6_src; 1152 d = (u_32_t *)&ip6->ip6_dst; 1153 plen = hl + ntohs(ip6->ip6_plen); 1154 go = 1; 1155 ehp = (struct ip6_ext *)((char *)ip6 + hl); 1156 while (go == 1) { 1157 switch (p) 1158 { 1159 case IPPROTO_HOPOPTS : 1160 case IPPROTO_MOBILITY : 1161 case IPPROTO_DSTOPTS : 1162 case IPPROTO_ROUTING : 1163 case IPPROTO_AH : 1164 p = ehp->ip6e_nxt; 1165 ehl = 8 + (ehp->ip6e_len << 3); 1166 hl += ehl; 1167 ehp = (struct ip6_ext *)((char *)ehp + ehl); 1168 break; 1169 case IPPROTO_FRAGMENT : 1170 hl += sizeof(struct ip6_frag); 1171 /* FALLTHROUGH */ 1172 default : 1173 go = 0; 1174 break; 1175 } 1176 } 1177 } else 1178 #endif 1179 { 1180 goto printipflog; 1181 } 1182 proto = getlocalproto(p); 1183 1184 if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 1185 tp = (tcphdr_t *)((char *)ip + hl); 1186 if (!(ipf->fl_lflags & FI_SHORT)) { 1187 sprintf(t, "%s,%s -> ", hostname(f, s), 1188 portlocalname(res, proto, (u_int)tp->th_sport)); 1189 t += strlen(t); 1190 sprintf(t, "%s,%s PR %s len %hu %hu", 1191 hostname(f, d), 1192 portlocalname(res, proto, (u_int)tp->th_dport), 1193 proto, hl, plen); 1194 t += strlen(t); 1195 1196 if (p == IPPROTO_TCP) { 1197 *t++ = ' '; 1198 *t++ = '-'; 1199 for (i = 0; tcpfl[i].value; i++) 1200 if (__tcp_get_flags(tp) & tcpfl[i].value) 1201 *t++ = tcpfl[i].flag; 1202 if (ipmonopts & IPMON_VERBOSE) { 1203 sprintf(t, " %lu %lu %hu", 1204 (u_long)(ntohl(tp->th_seq)), 1205 (u_long)(ntohl(tp->th_ack)), 1206 ntohs(tp->th_win)); 1207 t += strlen(t); 1208 } 1209 } 1210 *t = '\0'; 1211 } else { 1212 sprintf(t, "%s -> ", hostname(f, s)); 1213 t += strlen(t); 1214 sprintf(t, "%s PR %s len %hu %hu", 1215 hostname(f, d), proto, hl, plen); 1216 } 1217 #if defined(AF_INET6) && defined(IPPROTO_ICMPV6) 1218 } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { 1219 ic = (struct icmp *)((char *)ip + hl); 1220 sprintf(t, "%s -> ", hostname(f, s)); 1221 t += strlen(t); 1222 sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 1223 hostname(f, d), hl, plen, 1224 icmpname6(ic->icmp_type, ic->icmp_code)); 1225 #endif 1226 } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { 1227 ic = (struct icmp *)((char *)ip + hl); 1228 sprintf(t, "%s -> ", hostname(f, s)); 1229 t += strlen(t); 1230 sprintf(t, "%s PR icmp len %hu %hu icmp %s", 1231 hostname(f, d), hl, plen, 1232 icmpname(ic->icmp_type, ic->icmp_code)); 1233 if (ic->icmp_type == ICMP_UNREACH || 1234 ic->icmp_type == ICMP_SOURCEQUENCH || 1235 ic->icmp_type == ICMP_PARAMPROB || 1236 ic->icmp_type == ICMP_REDIRECT || 1237 ic->icmp_type == ICMP_TIMXCEED) { 1238 ipc = &ic->icmp_ip; 1239 i = ntohs(ipc->ip_len); 1240 /* 1241 * XXX - try to guess endian of ip_len in ICMP 1242 * returned data. 1243 */ 1244 if (i > 1500) 1245 i = ipc->ip_len; 1246 ipoff = ntohs(ipc->ip_off); 1247 proto = getlocalproto(ipc->ip_p); 1248 1249 if (!(ipoff & IP_OFFMASK) && 1250 ((ipc->ip_p == IPPROTO_TCP) || 1251 (ipc->ip_p == IPPROTO_UDP))) { 1252 tp = (tcphdr_t *)((char *)ipc + hl); 1253 t += strlen(t); 1254 sprintf(t, " for %s,%s -", 1255 HOSTNAMEV4(ipc->ip_src), 1256 portlocalname(res, proto, 1257 (u_int)tp->th_sport)); 1258 t += strlen(t); 1259 sprintf(t, " %s,%s PR %s len %hu %hu", 1260 HOSTNAMEV4(ipc->ip_dst), 1261 portlocalname(res, proto, 1262 (u_int)tp->th_dport), 1263 proto, IP_HL(ipc) << 2, i); 1264 } else if (!(ipoff & IP_OFFMASK) && 1265 (ipc->ip_p == IPPROTO_ICMP)) { 1266 icmp = (icmphdr_t *)((char *)ipc + hl); 1267 1268 t += strlen(t); 1269 sprintf(t, " for %s -", 1270 HOSTNAMEV4(ipc->ip_src)); 1271 t += strlen(t); 1272 sprintf(t, 1273 " %s PR icmp len %hu %hu icmp %d/%d", 1274 HOSTNAMEV4(ipc->ip_dst), 1275 IP_HL(ipc) << 2, i, 1276 icmp->icmp_type, icmp->icmp_code); 1277 } else { 1278 t += strlen(t); 1279 sprintf(t, " for %s -", 1280 HOSTNAMEV4(ipc->ip_src)); 1281 t += strlen(t); 1282 sprintf(t, " %s PR %s len %hu (%hu)", 1283 HOSTNAMEV4(ipc->ip_dst), proto, 1284 IP_HL(ipc) << 2, i); 1285 t += strlen(t); 1286 if (ipoff & IP_OFFMASK) { 1287 sprintf(t, "(frag %d:%hu@%hu%s%s)", 1288 ntohs(ipc->ip_id), 1289 i - (IP_HL(ipc) << 2), 1290 (ipoff & IP_OFFMASK) << 3, 1291 ipoff & IP_MF ? "+" : "", 1292 ipoff & IP_DF ? "-" : ""); 1293 } 1294 } 1295 1296 } 1297 } else { 1298 sprintf(t, "%s -> ", hostname(f, s)); 1299 t += strlen(t); 1300 sprintf(t, "%s PR %s len %hu (%hu)", 1301 hostname(f, d), proto, hl, plen); 1302 t += strlen(t); 1303 if (off & IP_OFFMASK) 1304 sprintf(t, " (frag %d:%hu@%hu%s%s)", 1305 ntohs(ip->ip_id), 1306 plen - hl, (off & IP_OFFMASK) << 3, 1307 ipoff & IP_MF ? "+" : "", 1308 ipoff & IP_DF ? "-" : ""); 1309 } 1310 t += strlen(t); 1311 1312 printipflog: 1313 if (ipf->fl_flags & FR_KEEPSTATE) { 1314 (void) strcpy(t, " K-S"); 1315 t += strlen(t); 1316 } 1317 1318 if (ipf->fl_flags & FR_KEEPFRAG) { 1319 (void) strcpy(t, " K-F"); 1320 t += strlen(t); 1321 } 1322 1323 if (ipf->fl_dir == 0) 1324 strcpy(t, " IN"); 1325 else if (ipf->fl_dir == 1) 1326 strcpy(t, " OUT"); 1327 t += strlen(t); 1328 if (ipf->fl_logtag != 0) { 1329 sprintf(t, " log-tag %d", ipf->fl_logtag); 1330 t += strlen(t); 1331 } 1332 if (ipf->fl_nattag.ipt_num[0] != 0) { 1333 strcpy(t, " nat-tag "); 1334 t += strlen(t); 1335 strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 1336 t += strlen(t); 1337 } 1338 if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 1339 strcpy(t, " low-ttl"); 1340 t += 8; 1341 } 1342 if ((ipf->fl_lflags & FI_OOW) != 0) { 1343 strcpy(t, " OOW"); 1344 t += 4; 1345 } 1346 if ((ipf->fl_lflags & FI_BAD) != 0) { 1347 strcpy(t, " bad"); 1348 t += 4; 1349 } 1350 if ((ipf->fl_lflags & FI_NATED) != 0) { 1351 strcpy(t, " NAT"); 1352 t += 4; 1353 } 1354 if ((ipf->fl_lflags & FI_BADNAT) != 0) { 1355 strcpy(t, " bad-NAT"); 1356 t += 8; 1357 } 1358 if ((ipf->fl_lflags & FI_BADSRC) != 0) { 1359 strcpy(t, " bad-src"); 1360 t += 8; 1361 } 1362 if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 1363 strcpy(t, " multicast"); 1364 t += 10; 1365 } 1366 if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 1367 strcpy(t, " broadcast"); 1368 t += 10; 1369 } 1370 if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 1371 FI_MBCAST) { 1372 strcpy(t, " mbcast"); 1373 t += 7; 1374 } 1375 if (ipf->fl_breason != 0) { 1376 strcpy(t, " reason:"); 1377 t += 8; 1378 strcpy(t, reasons[ipf->fl_breason]); 1379 t += strlen(reasons[ipf->fl_breason]); 1380 } 1381 *t++ = '\n'; 1382 *t++ = '\0'; 1383 defaction = 0; 1384 if (conf->cfile != NULL) 1385 defaction = check_action(buf, line, ipmonopts, lvl); 1386 1387 if (defaction == 0) { 1388 if (ipmonopts & IPMON_SYSLOG) { 1389 syslog(lvl, "%s", line); 1390 } else if (conf->log != NULL) { 1391 (void) fprintf(conf->log, "%s", line); 1392 } 1393 1394 if (ipmonopts & IPMON_HEXHDR) { 1395 dumphex(conf->log, ipmonopts, buf, 1396 sizeof(iplog_t) + sizeof(*ipf)); 1397 } 1398 if (ipmonopts & IPMON_HEXBODY) { 1399 dumphex(conf->log, ipmonopts, (char *)ip, 1400 ipf->fl_plen + ipf->fl_hlen); 1401 } else if ((ipmonopts & IPMON_LOGBODY) && 1402 (ipf->fl_flags & FR_LOGBODY)) { 1403 dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen, 1404 ipf->fl_plen); 1405 } 1406 } 1407 } 1408 1409 1410 static void 1411 usage(char *prog) 1412 { 1413 fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B <binary-logfile> ] [ -C <config-file> ]\n" 1414 "\t[ -f <device> ] [ -L <facility> ] [ -N <device> ]\n" 1415 "\t[ -o [NSI] ] [ -O [NSI] ] [ -P <pidfile> ] [ -S <device> ]\n" 1416 "\t[ <filename> ]\n", prog); 1417 exit(1); 1418 } 1419 1420 1421 static void 1422 write_pid(char *file) 1423 { 1424 FILE *fp = NULL; 1425 int fd; 1426 1427 if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 1428 fp = fdopen(fd, "w"); 1429 if (fp == NULL) { 1430 close(fd); 1431 fprintf(stderr, 1432 "unable to open/create pid file: %s\n", file); 1433 return; 1434 } 1435 fprintf(fp, "%d", getpid()); 1436 fclose(fp); 1437 } 1438 } 1439 1440 1441 static void 1442 flushlogs(char *file, FILE *log) 1443 { 1444 int fd, flushed = 0; 1445 1446 if ((fd = open(file, O_RDWR)) == -1) { 1447 (void) fprintf(stderr, "%s: open: %s\n", 1448 file, STRERROR(errno)); 1449 exit(1); 1450 } 1451 1452 if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 1453 printf("%d bytes flushed from log buffer\n", 1454 flushed); 1455 fflush(stdout); 1456 } else 1457 ipferror(fd, "SIOCIPFFB"); 1458 (void) close(fd); 1459 1460 if (flushed) { 1461 if (ipmonopts & IPMON_SYSLOG) { 1462 syslog(LOG_INFO, "%d bytes flushed from log\n", 1463 flushed); 1464 } else if ((log != stdout) && (log != NULL)) { 1465 fprintf(log, "%d bytes flushed from log\n", flushed); 1466 } 1467 } 1468 } 1469 1470 1471 static void 1472 logopts(int turnon, char *options) 1473 { 1474 int flags = 0; 1475 char *s; 1476 1477 for (s = options; *s; s++) 1478 { 1479 switch (*s) 1480 { 1481 case 'N' : 1482 flags |= IPMON_NAT; 1483 break; 1484 case 'S' : 1485 flags |= IPMON_STATE; 1486 break; 1487 case 'I' : 1488 flags |= IPMON_FILTER; 1489 break; 1490 default : 1491 fprintf(stderr, "Unknown log option %c\n", *s); 1492 exit(1); 1493 } 1494 } 1495 1496 if (turnon) 1497 ipmonopts |= flags; 1498 else 1499 ipmonopts &= ~(flags); 1500 } 1501 1502 static void 1503 initconfig(config_t *conf) 1504 { 1505 int i; 1506 1507 memset(conf, 0, sizeof(*conf)); 1508 1509 conf->log = stdout; 1510 conf->maxfd = -1; 1511 1512 for (i = 0; i < 3; i++) { 1513 conf->logsrc[i].fd = -1; 1514 conf->logsrc[i].logtype = -1; 1515 conf->logsrc[i].regular = -1; 1516 } 1517 1518 conf->logsrc[0].file = IPL_NAME; 1519 conf->logsrc[1].file = IPNAT_NAME; 1520 conf->logsrc[2].file = IPSTATE_NAME; 1521 1522 add_doing(&executesaver); 1523 add_doing(&snmpv1saver); 1524 add_doing(&snmpv2saver); 1525 add_doing(&syslogsaver); 1526 add_doing(&filesaver); 1527 add_doing(¬hingsaver); 1528 } 1529 1530 1531 int 1532 main(int argc, char *argv[]) 1533 { 1534 int doread, c, make_daemon = 0; 1535 char *prog; 1536 config_t config; 1537 1538 prog = strrchr(argv[0], '/'); 1539 if (prog == NULL) 1540 prog = argv[0]; 1541 else 1542 prog++; 1543 1544 initconfig(&config); 1545 1546 while ((c = getopt(argc, argv, 1547 "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) 1548 switch (c) 1549 { 1550 case 'a' : 1551 ipmonopts |= IPMON_LOGALL; 1552 config.logsrc[0].logtype = IPL_LOGIPF; 1553 config.logsrc[1].logtype = IPL_LOGNAT; 1554 config.logsrc[2].logtype = IPL_LOGSTATE; 1555 break; 1556 case 'b' : 1557 ipmonopts |= IPMON_LOGBODY; 1558 break; 1559 case 'B' : 1560 config.bfile = optarg; 1561 config.blog = fopen(optarg, "a"); 1562 break; 1563 case 'C' : 1564 config.cfile = optarg; 1565 break; 1566 case 'D' : 1567 make_daemon = 1; 1568 break; 1569 case 'f' : case 'I' : 1570 ipmonopts |= IPMON_FILTER; 1571 config.logsrc[0].logtype = IPL_LOGIPF; 1572 config.logsrc[0].file = optarg; 1573 break; 1574 case 'F' : 1575 flushlogs(config.logsrc[0].file, config.log); 1576 flushlogs(config.logsrc[1].file, config.log); 1577 flushlogs(config.logsrc[2].file, config.log); 1578 break; 1579 case 'L' : 1580 logfac = fac_findname(optarg); 1581 if (logfac == -1) { 1582 fprintf(stderr, 1583 "Unknown syslog facility '%s'\n", 1584 optarg); 1585 exit(1); 1586 } 1587 break; 1588 case 'n' : 1589 ipmonopts |= IPMON_RESOLVE; 1590 opts &= ~OPT_NORESOLVE; 1591 break; 1592 case 'N' : 1593 ipmonopts |= IPMON_NAT; 1594 config.logsrc[1].logtype = IPL_LOGNAT; 1595 config.logsrc[1].file = optarg; 1596 break; 1597 case 'o' : case 'O' : 1598 logopts(c == 'o', optarg); 1599 if (ipmonopts & IPMON_FILTER) 1600 config.logsrc[0].logtype = IPL_LOGIPF; 1601 if (ipmonopts & IPMON_NAT) 1602 config.logsrc[1].logtype = IPL_LOGNAT; 1603 if (ipmonopts & IPMON_STATE) 1604 config.logsrc[2].logtype = IPL_LOGSTATE; 1605 break; 1606 case 'p' : 1607 ipmonopts |= IPMON_PORTNUM; 1608 break; 1609 case 'P' : 1610 pidfile = optarg; 1611 break; 1612 case 's' : 1613 ipmonopts |= IPMON_SYSLOG; 1614 config.log = NULL; 1615 break; 1616 case 'S' : 1617 ipmonopts |= IPMON_STATE; 1618 config.logsrc[2].logtype = IPL_LOGSTATE; 1619 config.logsrc[2].file = optarg; 1620 break; 1621 case 't' : 1622 ipmonopts |= IPMON_TAIL; 1623 break; 1624 case 'v' : 1625 ipmonopts |= IPMON_VERBOSE; 1626 break; 1627 case 'x' : 1628 ipmonopts |= IPMON_HEXBODY; 1629 break; 1630 case 'X' : 1631 ipmonopts |= IPMON_HEXHDR; 1632 break; 1633 default : 1634 case 'h' : 1635 case '?' : 1636 usage(argv[0]); 1637 } 1638 1639 if (ipmonopts & IPMON_SYSLOG) 1640 openlog(prog, LOG_NDELAY|LOG_PID, logfac); 1641 1642 init_tabs(); 1643 if (config.cfile) 1644 if (load_config(config.cfile) == -1) { 1645 unload_config(); 1646 exit(1); 1647 } 1648 1649 /* 1650 * Default action is to only open the filter log file. 1651 */ 1652 if ((config.logsrc[0].logtype == -1) && 1653 (config.logsrc[0].logtype == -1) && 1654 (config.logsrc[0].logtype == -1)) 1655 config.logsrc[0].logtype = IPL_LOGIPF; 1656 1657 openlogs(&config); 1658 1659 if (!(ipmonopts & IPMON_SYSLOG)) { 1660 config.file = argv[optind]; 1661 config.log = config.file ? fopen(config.file, "a") : stdout; 1662 if (config.log == NULL) { 1663 (void) fprintf(stderr, "%s: fopen: %s\n", 1664 argv[optind], STRERROR(errno)); 1665 exit(1); 1666 /* NOTREACHED */ 1667 } 1668 setvbuf(config.log, NULL, _IONBF, 0); 1669 } else { 1670 config.log = NULL; 1671 } 1672 1673 if (make_daemon && 1674 ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { 1675 #ifdef BSD 1676 daemon(0, !(ipmonopts & IPMON_SYSLOG)); 1677 #else 1678 int pid; 1679 1680 switch (fork()) 1681 { 1682 case -1 : 1683 (void) fprintf(stderr, "%s: fork() failed: %s\n", 1684 argv[0], STRERROR(errno)); 1685 exit(1); 1686 /* NOTREACHED */ 1687 case 0 : 1688 break; 1689 default : 1690 exit(0); 1691 } 1692 1693 setsid(); 1694 if ((ipmonopts & IPMON_SYSLOG)) 1695 close(2); 1696 #endif /* !BSD */ 1697 close(0); 1698 close(1); 1699 write_pid(pidfile); 1700 } 1701 1702 signal(SIGHUP, handlehup); 1703 1704 for (doread = 1; doread; ) 1705 doread = read_loginfo(&config); 1706 1707 unload_config(); 1708 1709 return (0); 1710 /* NOTREACHED */ 1711 } 1712 1713 1714 static void 1715 openlogs(config_t *conf) 1716 { 1717 logsource_t *l; 1718 struct stat sb; 1719 int i; 1720 1721 for (i = 0; i < 3; i++) { 1722 l = &conf->logsrc[i]; 1723 if (l->logtype == -1) 1724 continue; 1725 if (!strcmp(l->file, "-")) 1726 l->fd = 0; 1727 else { 1728 if ((l->fd= open(l->file, O_RDONLY)) == -1) { 1729 (void) fprintf(stderr, 1730 "%s: open: %s\n", l->file, 1731 STRERROR(errno)); 1732 exit(1); 1733 /* NOTREACHED */ 1734 } 1735 1736 if (fstat(l->fd, &sb) == -1) { 1737 (void) fprintf(stderr, "%d: fstat: %s\n", 1738 l->fd, STRERROR(errno)); 1739 exit(1); 1740 /* NOTREACHED */ 1741 } 1742 1743 l->regular = !S_ISCHR(sb.st_mode); 1744 if (l->regular) 1745 l->size = sb.st_size; 1746 1747 FD_SET(l->fd, &conf->fdmr); 1748 if (l->fd > conf->maxfd) 1749 conf->maxfd = l->fd; 1750 } 1751 } 1752 } 1753 1754 1755 static int 1756 read_loginfo(config_t *conf) 1757 { 1758 iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1]; 1759 int n, tr, nr, i; 1760 logsource_t *l; 1761 fd_set fdr; 1762 1763 fdr = conf->fdmr; 1764 1765 n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL); 1766 if (n == 0) 1767 return (1); 1768 if (n == -1) { 1769 if (errno == EINTR) 1770 return (1); 1771 return (-1); 1772 } 1773 1774 for (i = 0, nr = 0; i < 3; i++) { 1775 l = &conf->logsrc[i]; 1776 1777 if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr)) 1778 continue; 1779 1780 tr = 0; 1781 if (l->regular) { 1782 tr = (lseek(l->fd, 0, SEEK_CUR) < l->size); 1783 if (!tr && !(ipmonopts & IPMON_TAIL)) 1784 return (0); 1785 } 1786 1787 n = 0; 1788 tr = read_log(l->fd, &n, (char *)buf, sizeof(buf)); 1789 if (donehup) { 1790 if (conf->file != NULL) { 1791 if (conf->log != NULL) { 1792 fclose(conf->log); 1793 conf->log = NULL; 1794 } 1795 conf->log = fopen(conf->file, "a"); 1796 } 1797 1798 if (conf->bfile != NULL) { 1799 if (conf->blog != NULL) { 1800 fclose(conf->blog); 1801 conf->blog = NULL; 1802 } 1803 conf->blog = fopen(conf->bfile, "a"); 1804 } 1805 1806 init_tabs(); 1807 if (conf->cfile != NULL) 1808 load_config(conf->cfile); 1809 donehup = 0; 1810 } 1811 1812 switch (tr) 1813 { 1814 case -1 : 1815 if (ipmonopts & IPMON_SYSLOG) 1816 syslog(LOG_CRIT, "read: %m\n"); 1817 else { 1818 ipferror(l->fd, "read"); 1819 } 1820 return (0); 1821 case 1 : 1822 if (ipmonopts & IPMON_SYSLOG) 1823 syslog(LOG_CRIT, "aborting logging\n"); 1824 else if (conf->log != NULL) 1825 fprintf(conf->log, "aborting logging\n"); 1826 return (0); 1827 case 2 : 1828 break; 1829 case 0 : 1830 nr += tr; 1831 if (n > 0) { 1832 print_log(conf, l, (char *)buf, n); 1833 if (!(ipmonopts & IPMON_SYSLOG)) 1834 fflush(conf->log); 1835 } 1836 break; 1837 } 1838 } 1839 1840 if (!nr && (ipmonopts & IPMON_TAIL)) 1841 sleep(1); 1842 1843 return (1); 1844 } 1845