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