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