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