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