ipmon.c revision 145510
1145510Sdarrenr/* $NetBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4145510Sdarrenr * Copyright (C) 1993-2001, 2003 by Darren Reed. 5145510Sdarrenr * 6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing. 7145510Sdarrenr */ 8145510Sdarrenr#ifndef SOLARIS 9145510Sdarrenr#define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun) 10145510Sdarrenr#endif 11145510Sdarrenr 12145510Sdarrenr#include <sys/types.h> 13145510Sdarrenr#include <sys/stat.h> 14145510Sdarrenr#include <sys/param.h> 15145510Sdarrenr#include <sys/file.h> 16145510Sdarrenr#include <sys/time.h> 17145510Sdarrenr#define _KERNEL 18145510Sdarrenr#include <sys/uio.h> 19145510Sdarrenr#undef _KERNEL 20145510Sdarrenr#include <sys/socket.h> 21145510Sdarrenr#include <sys/ioctl.h> 22145510Sdarrenr 23145510Sdarrenr#include <stdio.h> 24145510Sdarrenr#include <unistd.h> 25145510Sdarrenr#include <string.h> 26145510Sdarrenr#include <fcntl.h> 27145510Sdarrenr#include <errno.h> 28145510Sdarrenr#include <time.h> 29145510Sdarrenr#if !defined(__SVR4) && !defined(__svr4__) 30145510Sdarrenr# if (__FreeBSD_version >= 300000) 31145510Sdarrenr# include <sys/dirent.h> 32145510Sdarrenr# else 33145510Sdarrenr# include <sys/dir.h> 34145510Sdarrenr# endif 35145510Sdarrenr#else 36145510Sdarrenr# include <sys/filio.h> 37145510Sdarrenr# include <sys/byteorder.h> 38145510Sdarrenr#endif 39145510Sdarrenr#if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__)) 40145510Sdarrenr# include <strings.h> 41145510Sdarrenr#endif 42145510Sdarrenr#include <signal.h> 43145510Sdarrenr#include <stdlib.h> 44145510Sdarrenr#include <stddef.h> 45145510Sdarrenr#include <netinet/in.h> 46145510Sdarrenr#include <netinet/in_systm.h> 47145510Sdarrenr#include <net/if.h> 48145510Sdarrenr#include <netinet/ip.h> 49145510Sdarrenr#if !defined(__hpux) && !defined(linux) 50145510Sdarrenr# include <netinet/tcp_fsm.h> 51145510Sdarrenr#endif 52145510Sdarrenr#include <netdb.h> 53145510Sdarrenr#include <arpa/inet.h> 54145510Sdarrenr#include <arpa/nameser.h> 55145510Sdarrenr#ifdef __hpux 56145510Sdarrenr# undef NOERROR 57145510Sdarrenr#endif 58145510Sdarrenr#include <resolv.h> 59145510Sdarrenr 60145510Sdarrenr#if !defined(linux) 61145510Sdarrenr# include <sys/protosw.h> 62145510Sdarrenr# include <netinet/ip_var.h> 63145510Sdarrenr#endif 64145510Sdarrenr 65145510Sdarrenr#include <netinet/tcp.h> 66145510Sdarrenr#include <netinet/ip_icmp.h> 67145510Sdarrenr 68145510Sdarrenr#include <ctype.h> 69145510Sdarrenr#include <syslog.h> 70145510Sdarrenr 71145510Sdarrenr#include "netinet/ip_compat.h" 72145510Sdarrenr#include <netinet/tcpip.h> 73145510Sdarrenr#include "netinet/ip_fil.h" 74145510Sdarrenr#include "netinet/ip_nat.h" 75145510Sdarrenr#include "netinet/ip_state.h" 76145510Sdarrenr#include "netinet/ip_proxy.h" 77145510Sdarrenr#include "ipmon.h" 78145510Sdarrenr 79145510Sdarrenr#if !defined(lint) 80145510Sdarrenrstatic const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; 81145510Sdarrenrstatic const char rcsid[] = "@(#)Id: ipmon.c,v 1.33.2.8 2004/12/09 19:41:26 darrenr Exp"; 82145510Sdarrenr#endif 83145510Sdarrenr 84145510Sdarrenr 85145510Sdarrenr#if defined(sun) && !defined(SOLARIS2) 86145510Sdarrenr#define STRERROR(x) sys_errlist[x] 87145510Sdarrenrextern char *sys_errlist[]; 88145510Sdarrenr#else 89145510Sdarrenr#define STRERROR(x) strerror(x) 90145510Sdarrenr#endif 91145510Sdarrenr 92145510Sdarrenr 93145510Sdarrenrstruct flags { 94145510Sdarrenr int value; 95145510Sdarrenr char flag; 96145510Sdarrenr}; 97145510Sdarrenr 98145510Sdarrenr 99145510Sdarrenrtypedef struct icmp_subtype { 100145510Sdarrenr int ist_val; 101145510Sdarrenr char *ist_name; 102145510Sdarrenr} icmp_subtype_t; 103145510Sdarrenr 104145510Sdarrenrtypedef struct icmp_type { 105145510Sdarrenr int it_val; 106145510Sdarrenr struct icmp_subtype *it_subtable; 107145510Sdarrenr size_t it_stsize; 108145510Sdarrenr char *it_name; 109145510Sdarrenr} icmp_type_t; 110145510Sdarrenr 111145510Sdarrenr 112145510Sdarrenr#define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) 113145510Sdarrenr 114145510Sdarrenr 115145510Sdarrenrstruct flags tcpfl[] = { 116145510Sdarrenr { TH_ACK, 'A' }, 117145510Sdarrenr { TH_RST, 'R' }, 118145510Sdarrenr { TH_SYN, 'S' }, 119145510Sdarrenr { TH_FIN, 'F' }, 120145510Sdarrenr { TH_URG, 'U' }, 121145510Sdarrenr { TH_PUSH,'P' }, 122145510Sdarrenr { TH_ECN, 'E' }, 123145510Sdarrenr { TH_CWR, 'C' }, 124145510Sdarrenr { 0, '\0' } 125145510Sdarrenr}; 126145510Sdarrenr 127145510Sdarrenr#ifdef MENTAT 128145510Sdarrenrstatic char *pidfile = "/etc/opt/ipf/ipmon.pid"; 129145510Sdarrenr#else 130145510Sdarrenr# if BSD >= 199306 131145510Sdarrenrstatic char *pidfile = "/var/run/ipmon.pid"; 132145510Sdarrenr# else 133145510Sdarrenrstatic char *pidfile = "/etc/ipmon.pid"; 134145510Sdarrenr# endif 135145510Sdarrenr#endif 136145510Sdarrenr 137145510Sdarrenrstatic char line[2048]; 138145510Sdarrenrstatic int opts = 0; 139145510Sdarrenrstatic char *logfile = NULL; 140145510Sdarrenrstatic FILE *binarylog = NULL; 141145510Sdarrenrstatic char *binarylogfile = NULL; 142145510Sdarrenrstatic int donehup = 0; 143145510Sdarrenrstatic void usage __P((char *)); 144145510Sdarrenrstatic void handlehup __P((int)); 145145510Sdarrenrstatic void flushlogs __P((char *, FILE *)); 146145510Sdarrenrstatic void print_log __P((int, FILE *, char *, int)); 147145510Sdarrenrstatic void print_ipflog __P((FILE *, char *, int)); 148145510Sdarrenrstatic void print_natlog __P((FILE *, char *, int)); 149145510Sdarrenrstatic void print_statelog __P((FILE *, char *, int)); 150145510Sdarrenrstatic int read_log __P((int, int *, char *, int)); 151145510Sdarrenrstatic void write_pid __P((char *)); 152145510Sdarrenrstatic char *icmpname __P((u_int, u_int)); 153145510Sdarrenrstatic char *icmpname6 __P((u_int, u_int)); 154145510Sdarrenrstatic icmp_type_t *find_icmptype __P((int, icmp_type_t *, size_t)); 155145510Sdarrenrstatic icmp_subtype_t *find_icmpsubtype __P((int, icmp_subtype_t *, size_t)); 156145510Sdarrenr#ifdef __hpux 157145510Sdarrenrstatic struct tm *get_tm __P((u_32_t)); 158145510Sdarrenr#else 159145510Sdarrenrstatic struct tm *get_tm __P((time_t)); 160145510Sdarrenr#endif 161145510Sdarrenr 162145510Sdarrenrchar *hostname __P((int, int, u_32_t *)); 163145510Sdarrenrchar *portname __P((int, char *, u_int)); 164145510Sdarrenrint main __P((int, char *[])); 165145510Sdarrenr 166145510Sdarrenrstatic void logopts __P((int, char *)); 167145510Sdarrenrstatic void init_tabs __P((void)); 168145510Sdarrenrstatic char *getproto __P((u_int)); 169145510Sdarrenr 170145510Sdarrenrstatic char **protocols = NULL; 171145510Sdarrenrstatic char **udp_ports = NULL; 172145510Sdarrenrstatic char **tcp_ports = NULL; 173145510Sdarrenrstatic char *conf_file = NULL; 174145510Sdarrenr 175145510Sdarrenr 176145510Sdarrenr#define OPT_SYSLOG 0x001 177145510Sdarrenr#define OPT_RESOLVE 0x002 178145510Sdarrenr#define OPT_HEXBODY 0x004 179145510Sdarrenr#define OPT_VERBOSE 0x008 180145510Sdarrenr#define OPT_HEXHDR 0x010 181145510Sdarrenr#define OPT_TAIL 0x020 182145510Sdarrenr#define OPT_NAT 0x080 183145510Sdarrenr#define OPT_STATE 0x100 184145510Sdarrenr#define OPT_FILTER 0x200 185145510Sdarrenr#define OPT_PORTNUM 0x400 186145510Sdarrenr#define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) 187145510Sdarrenr#define OPT_LOGBODY 0x800 188145510Sdarrenr 189145510Sdarrenr#define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) 190145510Sdarrenr 191145510Sdarrenr#ifndef LOGFAC 192145510Sdarrenr#define LOGFAC LOG_LOCAL0 193145510Sdarrenr#endif 194145510Sdarrenr 195145510Sdarrenr 196145510Sdarrenrstatic icmp_subtype_t icmpunreachnames[] = { 197145510Sdarrenr { ICMP_UNREACH_NET, "net" }, 198145510Sdarrenr { ICMP_UNREACH_HOST, "host" }, 199145510Sdarrenr { ICMP_UNREACH_PROTOCOL, "protocol" }, 200145510Sdarrenr { ICMP_UNREACH_PORT, "port" }, 201145510Sdarrenr { ICMP_UNREACH_NEEDFRAG, "needfrag" }, 202145510Sdarrenr { ICMP_UNREACH_SRCFAIL, "srcfail" }, 203145510Sdarrenr { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, 204145510Sdarrenr { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, 205145510Sdarrenr { ICMP_UNREACH_NET, "isolated" }, 206145510Sdarrenr { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, 207145510Sdarrenr { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, 208145510Sdarrenr { ICMP_UNREACH_TOSNET, "tosnet" }, 209145510Sdarrenr { ICMP_UNREACH_TOSHOST, "toshost" }, 210145510Sdarrenr { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, 211145510Sdarrenr { -2, NULL } 212145510Sdarrenr}; 213145510Sdarrenr 214145510Sdarrenrstatic icmp_subtype_t redirectnames[] = { 215145510Sdarrenr { ICMP_REDIRECT_NET, "net" }, 216145510Sdarrenr { ICMP_REDIRECT_HOST, "host" }, 217145510Sdarrenr { ICMP_REDIRECT_TOSNET, "tosnet" }, 218145510Sdarrenr { ICMP_REDIRECT_TOSHOST, "toshost" }, 219145510Sdarrenr { -2, NULL } 220145510Sdarrenr}; 221145510Sdarrenr 222145510Sdarrenrstatic icmp_subtype_t timxceednames[] = { 223145510Sdarrenr { ICMP_TIMXCEED_INTRANS, "transit" }, 224145510Sdarrenr { ICMP_TIMXCEED_REASS, "reassem" }, 225145510Sdarrenr { -2, NULL } 226145510Sdarrenr}; 227145510Sdarrenr 228145510Sdarrenrstatic icmp_subtype_t paramnames[] = { 229145510Sdarrenr { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, 230145510Sdarrenr { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, 231145510Sdarrenr { ICMP_PARAMPROB_LENGTH, "length" }, 232145510Sdarrenr { -2, NULL } 233145510Sdarrenr}; 234145510Sdarrenr 235145510Sdarrenrstatic icmp_type_t icmptypes[] = { 236145510Sdarrenr { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, 237145510Sdarrenr { -1, NULL, 0, NULL }, 238145510Sdarrenr { -1, NULL, 0, NULL }, 239145510Sdarrenr { ICMP_UNREACH, icmpunreachnames, 240145510Sdarrenr IST_SZ(icmpunreachnames),"unreach" }, 241145510Sdarrenr { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, 242145510Sdarrenr { ICMP_REDIRECT, redirectnames, 243145510Sdarrenr IST_SZ(redirectnames), "redirect" }, 244145510Sdarrenr { -1, NULL, 0, NULL }, 245145510Sdarrenr { -1, NULL, 0, NULL }, 246145510Sdarrenr { ICMP_ECHO, NULL, 0, "echo" }, 247145510Sdarrenr { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, 248145510Sdarrenr { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, 249145510Sdarrenr { ICMP_TIMXCEED, timxceednames, 250145510Sdarrenr IST_SZ(timxceednames), "timxceed" }, 251145510Sdarrenr { ICMP_PARAMPROB, paramnames, 252145510Sdarrenr IST_SZ(paramnames), "paramprob" }, 253145510Sdarrenr { ICMP_TSTAMP, NULL, 0, "timestamp" }, 254145510Sdarrenr { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, 255145510Sdarrenr { ICMP_IREQ, NULL, 0, "inforeq" }, 256145510Sdarrenr { ICMP_IREQREPLY, NULL, 0, "inforeply" }, 257145510Sdarrenr { ICMP_MASKREQ, NULL, 0, "maskreq" }, 258145510Sdarrenr { ICMP_MASKREPLY, NULL, 0, "maskreply" }, 259145510Sdarrenr { -2, NULL, 0, NULL } 260145510Sdarrenr}; 261145510Sdarrenr 262145510Sdarrenrstatic icmp_subtype_t icmpredirect6[] = { 263145510Sdarrenr { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, 264145510Sdarrenr { ICMP6_DST_UNREACH_ADMIN, "admin" }, 265145510Sdarrenr { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, 266145510Sdarrenr { ICMP6_DST_UNREACH_ADDR, "address" }, 267145510Sdarrenr { ICMP6_DST_UNREACH_NOPORT, "noport" }, 268145510Sdarrenr { -2, NULL } 269145510Sdarrenr}; 270145510Sdarrenr 271145510Sdarrenrstatic icmp_subtype_t icmptimexceed6[] = { 272145510Sdarrenr { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, 273145510Sdarrenr { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, 274145510Sdarrenr { -2, NULL } 275145510Sdarrenr}; 276145510Sdarrenr 277145510Sdarrenrstatic icmp_subtype_t icmpparamprob6[] = { 278145510Sdarrenr { ICMP6_PARAMPROB_HEADER, "header" }, 279145510Sdarrenr { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, 280145510Sdarrenr { ICMP6_PARAMPROB_OPTION, "option" }, 281145510Sdarrenr { -2, NULL } 282145510Sdarrenr}; 283145510Sdarrenr 284145510Sdarrenrstatic icmp_subtype_t icmpquerysubject6[] = { 285145510Sdarrenr { ICMP6_NI_SUBJ_IPV6, "ipv6" }, 286145510Sdarrenr { ICMP6_NI_SUBJ_FQDN, "fqdn" }, 287145510Sdarrenr { ICMP6_NI_SUBJ_IPV4, "ipv4" }, 288145510Sdarrenr { -2, NULL }, 289145510Sdarrenr}; 290145510Sdarrenr 291145510Sdarrenrstatic icmp_subtype_t icmpnodeinfo6[] = { 292145510Sdarrenr { ICMP6_NI_SUCCESS, "success" }, 293145510Sdarrenr { ICMP6_NI_REFUSED, "refused" }, 294145510Sdarrenr { ICMP6_NI_UNKNOWN, "unknown" }, 295145510Sdarrenr { -2, NULL } 296145510Sdarrenr}; 297145510Sdarrenr 298145510Sdarrenrstatic icmp_subtype_t icmprenumber6[] = { 299145510Sdarrenr { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, 300145510Sdarrenr { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, 301145510Sdarrenr { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, 302145510Sdarrenr { -2, NULL } 303145510Sdarrenr}; 304145510Sdarrenr 305145510Sdarrenrstatic icmp_type_t icmptypes6[] = { 306145510Sdarrenr { 0, NULL, 0, NULL }, 307145510Sdarrenr { ICMP6_DST_UNREACH, icmpredirect6, 308145510Sdarrenr IST_SZ(icmpredirect6), "unreach" }, 309145510Sdarrenr { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, 310145510Sdarrenr { ICMP6_TIME_EXCEEDED, icmptimexceed6, 311145510Sdarrenr IST_SZ(icmptimexceed6), "timxceed" }, 312145510Sdarrenr { ICMP6_PARAM_PROB, icmpparamprob6, 313145510Sdarrenr IST_SZ(icmpparamprob6), "paramprob" }, 314145510Sdarrenr { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, 315145510Sdarrenr { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, 316145510Sdarrenr { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, 317145510Sdarrenr IST_SZ(icmpquerysubject6), "groupmemberquery" }, 318145510Sdarrenr { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, 319145510Sdarrenr { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, 320145510Sdarrenr { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, 321145510Sdarrenr { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, 322145510Sdarrenr { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, 323145510Sdarrenr { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, 324145510Sdarrenr { ND_REDIRECT, NULL, 0, "redirect" }, 325145510Sdarrenr { ICMP6_ROUTER_RENUMBERING, icmprenumber6, 326145510Sdarrenr IST_SZ(icmprenumber6), "routerrenumber" }, 327145510Sdarrenr { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, 328145510Sdarrenr { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, 329145510Sdarrenr { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, 330145510Sdarrenr { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, 331145510Sdarrenr { ICMP6_NI_QUERY, icmpnodeinfo6, 332145510Sdarrenr IST_SZ(icmpnodeinfo6), "nodeinforequest" }, 333145510Sdarrenr { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, 334145510Sdarrenr { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, 335145510Sdarrenr { MLD6_MTRACE, NULL, 0, "mtracerequest" }, 336145510Sdarrenr { -2, NULL, 0, NULL } 337145510Sdarrenr}; 338145510Sdarrenr 339145510Sdarrenrstatic icmp_subtype_t *find_icmpsubtype(type, table, tablesz) 340145510Sdarrenrint type; 341145510Sdarrenricmp_subtype_t *table; 342145510Sdarrenrsize_t tablesz; 343145510Sdarrenr{ 344145510Sdarrenr icmp_subtype_t *ist; 345145510Sdarrenr int i; 346145510Sdarrenr 347145510Sdarrenr if (tablesz < 2) 348145510Sdarrenr return NULL; 349145510Sdarrenr 350145510Sdarrenr if ((type < 0) || (type > table[tablesz - 2].ist_val)) 351145510Sdarrenr return NULL; 352145510Sdarrenr 353145510Sdarrenr i = type; 354145510Sdarrenr if (table[type].ist_val == type) 355145510Sdarrenr return table + type; 356145510Sdarrenr 357145510Sdarrenr for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) 358145510Sdarrenr if (ist->ist_val == type) 359145510Sdarrenr return ist; 360145510Sdarrenr return NULL; 361145510Sdarrenr} 362145510Sdarrenr 363145510Sdarrenr 364145510Sdarrenrstatic icmp_type_t *find_icmptype(type, table, tablesz) 365145510Sdarrenrint type; 366145510Sdarrenricmp_type_t *table; 367145510Sdarrenrsize_t tablesz; 368145510Sdarrenr{ 369145510Sdarrenr icmp_type_t *it; 370145510Sdarrenr int i; 371145510Sdarrenr 372145510Sdarrenr if (tablesz < 2) 373145510Sdarrenr return NULL; 374145510Sdarrenr 375145510Sdarrenr if ((type < 0) || (type > table[tablesz - 2].it_val)) 376145510Sdarrenr return NULL; 377145510Sdarrenr 378145510Sdarrenr i = type; 379145510Sdarrenr if (table[type].it_val == type) 380145510Sdarrenr return table + type; 381145510Sdarrenr 382145510Sdarrenr for (i = 0, it = table; it->it_val != -2; i++, it++) 383145510Sdarrenr if (it->it_val == type) 384145510Sdarrenr return it; 385145510Sdarrenr return NULL; 386145510Sdarrenr} 387145510Sdarrenr 388145510Sdarrenr 389145510Sdarrenrstatic void handlehup(sig) 390145510Sdarrenrint sig; 391145510Sdarrenr{ 392145510Sdarrenr signal(SIGHUP, handlehup); 393145510Sdarrenr donehup = 1; 394145510Sdarrenr} 395145510Sdarrenr 396145510Sdarrenr 397145510Sdarrenrstatic void init_tabs() 398145510Sdarrenr{ 399145510Sdarrenr struct protoent *p; 400145510Sdarrenr struct servent *s; 401145510Sdarrenr char *name, **tab; 402145510Sdarrenr int port, i; 403145510Sdarrenr 404145510Sdarrenr if (protocols != NULL) { 405145510Sdarrenr for (i = 0; i < 256; i++) 406145510Sdarrenr if (protocols[i] != NULL) { 407145510Sdarrenr free(protocols[i]); 408145510Sdarrenr protocols[i] = NULL; 409145510Sdarrenr } 410145510Sdarrenr free(protocols); 411145510Sdarrenr protocols = NULL; 412145510Sdarrenr } 413145510Sdarrenr protocols = (char **)malloc(256 * sizeof(*protocols)); 414145510Sdarrenr if (protocols != NULL) { 415145510Sdarrenr bzero((char *)protocols, 256 * sizeof(*protocols)); 416145510Sdarrenr 417145510Sdarrenr setprotoent(1); 418145510Sdarrenr while ((p = getprotoent()) != NULL) 419145510Sdarrenr if (p->p_proto >= 0 && p->p_proto <= 255 && 420145510Sdarrenr p->p_name != NULL && protocols[p->p_proto] == NULL) 421145510Sdarrenr protocols[p->p_proto] = strdup(p->p_name); 422145510Sdarrenr endprotoent(); 423145510Sdarrenr } 424145510Sdarrenr 425145510Sdarrenr if (udp_ports != NULL) { 426145510Sdarrenr for (i = 0; i < 65536; i++) 427145510Sdarrenr if (udp_ports[i] != NULL) { 428145510Sdarrenr free(udp_ports[i]); 429145510Sdarrenr udp_ports[i] = NULL; 430145510Sdarrenr } 431145510Sdarrenr free(udp_ports); 432145510Sdarrenr udp_ports = NULL; 433145510Sdarrenr } 434145510Sdarrenr udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 435145510Sdarrenr if (udp_ports != NULL) 436145510Sdarrenr bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 437145510Sdarrenr 438145510Sdarrenr if (tcp_ports != NULL) { 439145510Sdarrenr for (i = 0; i < 65536; i++) 440145510Sdarrenr if (tcp_ports[i] != NULL) { 441145510Sdarrenr free(tcp_ports[i]); 442145510Sdarrenr tcp_ports[i] = NULL; 443145510Sdarrenr } 444145510Sdarrenr free(tcp_ports); 445145510Sdarrenr tcp_ports = NULL; 446145510Sdarrenr } 447145510Sdarrenr tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 448145510Sdarrenr if (tcp_ports != NULL) 449145510Sdarrenr bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 450145510Sdarrenr 451145510Sdarrenr setservent(1); 452145510Sdarrenr while ((s = getservent()) != NULL) { 453145510Sdarrenr if (s->s_proto == NULL) 454145510Sdarrenr continue; 455145510Sdarrenr else if (!strcmp(s->s_proto, "tcp")) { 456145510Sdarrenr port = ntohs(s->s_port); 457145510Sdarrenr name = s->s_name; 458145510Sdarrenr tab = tcp_ports; 459145510Sdarrenr } else if (!strcmp(s->s_proto, "udp")) { 460145510Sdarrenr port = ntohs(s->s_port); 461145510Sdarrenr name = s->s_name; 462145510Sdarrenr tab = udp_ports; 463145510Sdarrenr } else 464145510Sdarrenr continue; 465145510Sdarrenr if ((port < 0 || port > 65535) || (name == NULL)) 466145510Sdarrenr continue; 467145510Sdarrenr if (tab != NULL) 468145510Sdarrenr tab[port] = strdup(name); 469145510Sdarrenr } 470145510Sdarrenr endservent(); 471145510Sdarrenr} 472145510Sdarrenr 473145510Sdarrenr 474145510Sdarrenrstatic char *getproto(p) 475145510Sdarrenru_int p; 476145510Sdarrenr{ 477145510Sdarrenr static char pnum[4]; 478145510Sdarrenr char *s; 479145510Sdarrenr 480145510Sdarrenr p &= 0xff; 481145510Sdarrenr s = protocols ? protocols[p] : NULL; 482145510Sdarrenr if (s == NULL) { 483145510Sdarrenr sprintf(pnum, "%u", p); 484145510Sdarrenr s = pnum; 485145510Sdarrenr } 486145510Sdarrenr return s; 487145510Sdarrenr} 488145510Sdarrenr 489145510Sdarrenr 490145510Sdarrenrstatic int read_log(fd, lenp, buf, bufsize) 491145510Sdarrenrint fd, bufsize, *lenp; 492145510Sdarrenrchar *buf; 493145510Sdarrenr{ 494145510Sdarrenr int nr; 495145510Sdarrenr 496145510Sdarrenr nr = read(fd, buf, bufsize); 497145510Sdarrenr if (!nr) 498145510Sdarrenr return 2; 499145510Sdarrenr if ((nr < 0) && (errno != EINTR)) 500145510Sdarrenr return -1; 501145510Sdarrenr *lenp = nr; 502145510Sdarrenr return 0; 503145510Sdarrenr} 504145510Sdarrenr 505145510Sdarrenr 506145510Sdarrenrchar *hostname(res, v, ip) 507145510Sdarrenrint res, v; 508145510Sdarrenru_32_t *ip; 509145510Sdarrenr{ 510145510Sdarrenr# define MAX_INETA 16 511145510Sdarrenr static char hname[MAXHOSTNAMELEN + MAX_INETA + 3]; 512145510Sdarrenr#ifdef USE_INET6 513145510Sdarrenr static char hostbuf[MAXHOSTNAMELEN+1]; 514145510Sdarrenr#endif 515145510Sdarrenr struct hostent *hp; 516145510Sdarrenr struct in_addr ipa; 517145510Sdarrenr 518145510Sdarrenr if (v == 4) { 519145510Sdarrenr ipa.s_addr = *ip; 520145510Sdarrenr if (!res) 521145510Sdarrenr return inet_ntoa(ipa); 522145510Sdarrenr hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET); 523145510Sdarrenr if (!hp) 524145510Sdarrenr return inet_ntoa(ipa); 525145510Sdarrenr sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, 526145510Sdarrenr inet_ntoa(ipa)); 527145510Sdarrenr return hname; 528145510Sdarrenr } 529145510Sdarrenr#ifdef USE_INET6 530145510Sdarrenr (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); 531145510Sdarrenr hostbuf[MAXHOSTNAMELEN] = '\0'; 532145510Sdarrenr return hostbuf; 533145510Sdarrenr#else 534145510Sdarrenr return "IPv6"; 535145510Sdarrenr#endif 536145510Sdarrenr} 537145510Sdarrenr 538145510Sdarrenr 539145510Sdarrenrchar *portname(res, proto, port) 540145510Sdarrenrint res; 541145510Sdarrenrchar *proto; 542145510Sdarrenru_int port; 543145510Sdarrenr{ 544145510Sdarrenr static char pname[8]; 545145510Sdarrenr char *s; 546145510Sdarrenr 547145510Sdarrenr port = ntohs(port); 548145510Sdarrenr port &= 0xffff; 549145510Sdarrenr (void) sprintf(pname, "%u", port); 550145510Sdarrenr if (!res || (opts & OPT_PORTNUM)) 551145510Sdarrenr return pname; 552145510Sdarrenr s = NULL; 553145510Sdarrenr if (!strcmp(proto, "tcp")) 554145510Sdarrenr s = tcp_ports[port]; 555145510Sdarrenr else if (!strcmp(proto, "udp")) 556145510Sdarrenr s = udp_ports[port]; 557145510Sdarrenr if (s == NULL) 558145510Sdarrenr s = pname; 559145510Sdarrenr return s; 560145510Sdarrenr} 561145510Sdarrenr 562145510Sdarrenr 563145510Sdarrenrstatic char *icmpname(type, code) 564145510Sdarrenru_int type; 565145510Sdarrenru_int code; 566145510Sdarrenr{ 567145510Sdarrenr static char name[80]; 568145510Sdarrenr icmp_subtype_t *ist; 569145510Sdarrenr icmp_type_t *it; 570145510Sdarrenr char *s; 571145510Sdarrenr 572145510Sdarrenr s = NULL; 573145510Sdarrenr it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it)); 574145510Sdarrenr if (it != NULL) 575145510Sdarrenr s = it->it_name; 576145510Sdarrenr 577145510Sdarrenr if (s == NULL) 578145510Sdarrenr sprintf(name, "icmptype(%d)/", type); 579145510Sdarrenr else 580145510Sdarrenr sprintf(name, "%s/", s); 581145510Sdarrenr 582145510Sdarrenr ist = NULL; 583145510Sdarrenr if (it != NULL && it->it_subtable != NULL) 584145510Sdarrenr ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 585145510Sdarrenr 586145510Sdarrenr if (ist != NULL && ist->ist_name != NULL) 587145510Sdarrenr strcat(name, ist->ist_name); 588145510Sdarrenr else 589145510Sdarrenr sprintf(name + strlen(name), "%d", code); 590145510Sdarrenr 591145510Sdarrenr return name; 592145510Sdarrenr} 593145510Sdarrenr 594145510Sdarrenrstatic char *icmpname6(type, code) 595145510Sdarrenru_int type; 596145510Sdarrenru_int code; 597145510Sdarrenr{ 598145510Sdarrenr static char name[80]; 599145510Sdarrenr icmp_subtype_t *ist; 600145510Sdarrenr icmp_type_t *it; 601145510Sdarrenr char *s; 602145510Sdarrenr 603145510Sdarrenr s = NULL; 604145510Sdarrenr it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 605145510Sdarrenr if (it != NULL) 606145510Sdarrenr s = it->it_name; 607145510Sdarrenr 608145510Sdarrenr if (s == NULL) 609145510Sdarrenr sprintf(name, "icmpv6type(%d)/", type); 610145510Sdarrenr else 611145510Sdarrenr sprintf(name, "%s/", s); 612145510Sdarrenr 613145510Sdarrenr ist = NULL; 614145510Sdarrenr if (it != NULL && it->it_subtable != NULL) 615145510Sdarrenr ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 616145510Sdarrenr 617145510Sdarrenr if (ist != NULL && ist->ist_name != NULL) 618145510Sdarrenr strcat(name, ist->ist_name); 619145510Sdarrenr else 620145510Sdarrenr sprintf(name + strlen(name), "%d", code); 621145510Sdarrenr 622145510Sdarrenr return name; 623145510Sdarrenr} 624145510Sdarrenr 625145510Sdarrenr 626145510Sdarrenrvoid dumphex(log, dopts, buf, len) 627145510SdarrenrFILE *log; 628145510Sdarrenrint dopts; 629145510Sdarrenrchar *buf; 630145510Sdarrenrint len; 631145510Sdarrenr{ 632145510Sdarrenr char hline[80]; 633145510Sdarrenr int i, j, k; 634145510Sdarrenr u_char *s = (u_char *)buf, *t = (u_char *)hline; 635145510Sdarrenr 636145510Sdarrenr if (buf == NULL || len == 0) 637145510Sdarrenr return; 638145510Sdarrenr 639145510Sdarrenr *hline = '\0'; 640145510Sdarrenr 641145510Sdarrenr for (i = len, j = 0; i; i--, j++, s++) { 642145510Sdarrenr if (j && !(j & 0xf)) { 643145510Sdarrenr *t++ = '\n'; 644145510Sdarrenr *t = '\0'; 645145510Sdarrenr if (!(dopts & OPT_SYSLOG)) 646145510Sdarrenr fputs(hline, log); 647145510Sdarrenr else 648145510Sdarrenr syslog(LOG_INFO, "%s", hline); 649145510Sdarrenr t = (u_char *)hline; 650145510Sdarrenr *t = '\0'; 651145510Sdarrenr } 652145510Sdarrenr sprintf((char *)t, "%02x", *s & 0xff); 653145510Sdarrenr t += 2; 654145510Sdarrenr if (!((j + 1) & 0xf)) { 655145510Sdarrenr s -= 15; 656145510Sdarrenr sprintf((char *)t, " "); 657145510Sdarrenr t += 8; 658145510Sdarrenr for (k = 16; k; k--, s++) 659145510Sdarrenr *t++ = (ISPRINT(*s) ? *s : '.'); 660145510Sdarrenr s--; 661145510Sdarrenr } 662145510Sdarrenr 663145510Sdarrenr if ((j + 1) & 0xf) 664145510Sdarrenr *t++ = ' ';; 665145510Sdarrenr } 666145510Sdarrenr 667145510Sdarrenr if (j & 0xf) { 668145510Sdarrenr for (k = 16 - (j & 0xf); k; k--) { 669145510Sdarrenr *t++ = ' '; 670145510Sdarrenr *t++ = ' '; 671145510Sdarrenr *t++ = ' '; 672145510Sdarrenr } 673145510Sdarrenr sprintf((char *)t, " "); 674145510Sdarrenr t += 7; 675145510Sdarrenr s -= j & 0xf; 676145510Sdarrenr for (k = j & 0xf; k; k--, s++) 677145510Sdarrenr *t++ = (ISPRINT(*s) ? *s : '.'); 678145510Sdarrenr *t++ = '\n'; 679145510Sdarrenr *t = '\0'; 680145510Sdarrenr } 681145510Sdarrenr if (!(dopts & OPT_SYSLOG)) { 682145510Sdarrenr fputs(hline, log); 683145510Sdarrenr fflush(log); 684145510Sdarrenr } else 685145510Sdarrenr syslog(LOG_INFO, "%s", hline); 686145510Sdarrenr} 687145510Sdarrenr 688145510Sdarrenr 689145510Sdarrenrstatic struct tm *get_tm(sec) 690145510Sdarrenr#ifdef __hpux 691145510Sdarrenru_32_t sec; 692145510Sdarrenr#else 693145510Sdarrenrtime_t sec; 694145510Sdarrenr#endif 695145510Sdarrenr{ 696145510Sdarrenr struct tm *tm; 697145510Sdarrenr time_t t; 698145510Sdarrenr 699145510Sdarrenr t = sec; 700145510Sdarrenr tm = localtime(&t); 701145510Sdarrenr return tm; 702145510Sdarrenr} 703145510Sdarrenr 704145510Sdarrenrstatic void print_natlog(log, buf, blen) 705145510SdarrenrFILE *log; 706145510Sdarrenrchar *buf; 707145510Sdarrenrint blen; 708145510Sdarrenr{ 709145510Sdarrenr struct natlog *nl; 710145510Sdarrenr iplog_t *ipl = (iplog_t *)buf; 711145510Sdarrenr char *t = line; 712145510Sdarrenr struct tm *tm; 713145510Sdarrenr int res, i, len; 714145510Sdarrenr char *proto; 715145510Sdarrenr 716145510Sdarrenr nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 717145510Sdarrenr res = (opts & OPT_RESOLVE) ? 1 : 0; 718145510Sdarrenr tm = get_tm(ipl->ipl_sec); 719145510Sdarrenr len = sizeof(line); 720145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 721145510Sdarrenr (void) strftime(t, len, "%d/%m/%Y ", tm); 722145510Sdarrenr i = strlen(t); 723145510Sdarrenr len -= i; 724145510Sdarrenr t += i; 725145510Sdarrenr } 726145510Sdarrenr (void) strftime(t, len, "%T", tm); 727145510Sdarrenr t += strlen(t); 728145510Sdarrenr (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1); 729145510Sdarrenr t += strlen(t); 730145510Sdarrenr 731145510Sdarrenr if (nl->nl_type == NL_NEWMAP) 732145510Sdarrenr strcpy(t, "NAT:MAP "); 733145510Sdarrenr else if (nl->nl_type == NL_NEWRDR) 734145510Sdarrenr strcpy(t, "NAT:RDR "); 735145510Sdarrenr else if (nl->nl_type == NL_FLUSH) 736145510Sdarrenr strcpy(t, "NAT:FLUSH "); 737145510Sdarrenr else if (nl->nl_type == NL_EXPIRE) 738145510Sdarrenr strcpy(t, "NAT:EXPIRE "); 739145510Sdarrenr else if (nl->nl_type == NL_NEWBIMAP) 740145510Sdarrenr strcpy(t, "NAT:BIMAP "); 741145510Sdarrenr else if (nl->nl_type == NL_NEWBLOCK) 742145510Sdarrenr strcpy(t, "NAT:MAPBLOCK "); 743145510Sdarrenr else if (nl->nl_type == NL_CLONE) 744145510Sdarrenr strcpy(t, "NAT:CLONE "); 745145510Sdarrenr else 746145510Sdarrenr sprintf(t, "Type: %d ", nl->nl_type); 747145510Sdarrenr t += strlen(t); 748145510Sdarrenr 749145510Sdarrenr proto = getproto(nl->nl_p); 750145510Sdarrenr 751145510Sdarrenr (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), 752145510Sdarrenr portname(res, proto, (u_int)nl->nl_inport)); 753145510Sdarrenr t += strlen(t); 754145510Sdarrenr (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), 755145510Sdarrenr portname(res, proto, (u_int)nl->nl_outport)); 756145510Sdarrenr t += strlen(t); 757145510Sdarrenr (void) sprintf(t, "[%s,%s]", HOSTNAME_V4(res, nl->nl_origip), 758145510Sdarrenr portname(res, proto, (u_int)nl->nl_origport)); 759145510Sdarrenr t += strlen(t); 760145510Sdarrenr if (nl->nl_type == NL_EXPIRE) { 761145510Sdarrenr#ifdef USE_QUAD_T 762145510Sdarrenr (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 763145510Sdarrenr (long long)nl->nl_pkts[0], 764145510Sdarrenr (long long)nl->nl_pkts[1], 765145510Sdarrenr (long long)nl->nl_bytes[0], 766145510Sdarrenr (long long)nl->nl_bytes[1]); 767145510Sdarrenr#else 768145510Sdarrenr (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 769145510Sdarrenr nl->nl_pkts[0], nl->nl_pkts[1], 770145510Sdarrenr nl->nl_bytes[0], nl->nl_bytes[1]); 771145510Sdarrenr#endif 772145510Sdarrenr t += strlen(t); 773145510Sdarrenr } 774145510Sdarrenr 775145510Sdarrenr *t++ = '\n'; 776145510Sdarrenr *t++ = '\0'; 777145510Sdarrenr if (opts & OPT_SYSLOG) 778145510Sdarrenr syslog(LOG_INFO, "%s", line); 779145510Sdarrenr else 780145510Sdarrenr (void) fprintf(log, "%s", line); 781145510Sdarrenr} 782145510Sdarrenr 783145510Sdarrenr 784145510Sdarrenrstatic void print_statelog(log, buf, blen) 785145510SdarrenrFILE *log; 786145510Sdarrenrchar *buf; 787145510Sdarrenrint blen; 788145510Sdarrenr{ 789145510Sdarrenr struct ipslog *sl; 790145510Sdarrenr iplog_t *ipl = (iplog_t *)buf; 791145510Sdarrenr char *t = line, *proto; 792145510Sdarrenr struct tm *tm; 793145510Sdarrenr int res, i, len; 794145510Sdarrenr 795145510Sdarrenr sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 796145510Sdarrenr res = (opts & OPT_RESOLVE) ? 1 : 0; 797145510Sdarrenr tm = get_tm(ipl->ipl_sec); 798145510Sdarrenr len = sizeof(line); 799145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 800145510Sdarrenr (void) strftime(t, len, "%d/%m/%Y ", tm); 801145510Sdarrenr i = strlen(t); 802145510Sdarrenr len -= i; 803145510Sdarrenr t += i; 804145510Sdarrenr } 805145510Sdarrenr (void) strftime(t, len, "%T", tm); 806145510Sdarrenr t += strlen(t); 807145510Sdarrenr (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 808145510Sdarrenr t += strlen(t); 809145510Sdarrenr 810145510Sdarrenr if (sl->isl_type == ISL_NEW) 811145510Sdarrenr strcpy(t, "STATE:NEW "); 812145510Sdarrenr else if (sl->isl_type == ISL_CLONE) 813145510Sdarrenr strcpy(t, "STATE:CLONED "); 814145510Sdarrenr else if (sl->isl_type == ISL_EXPIRE) { 815145510Sdarrenr if ((sl->isl_p == IPPROTO_TCP) && 816145510Sdarrenr (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 817145510Sdarrenr sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 818145510Sdarrenr strcpy(t, "STATE:CLOSE "); 819145510Sdarrenr else 820145510Sdarrenr strcpy(t, "STATE:EXPIRE "); 821145510Sdarrenr } else if (sl->isl_type == ISL_FLUSH) 822145510Sdarrenr strcpy(t, "STATE:FLUSH "); 823145510Sdarrenr else if (sl->isl_type == ISL_INTERMEDIATE) 824145510Sdarrenr strcpy(t, "STATE:INTERMEDIATE "); 825145510Sdarrenr else if (sl->isl_type == ISL_REMOVE) 826145510Sdarrenr strcpy(t, "STATE:REMOVE "); 827145510Sdarrenr else if (sl->isl_type == ISL_KILLED) 828145510Sdarrenr strcpy(t, "STATE:KILLED "); 829145510Sdarrenr else 830145510Sdarrenr sprintf(t, "Type: %d ", sl->isl_type); 831145510Sdarrenr t += strlen(t); 832145510Sdarrenr 833145510Sdarrenr proto = getproto(sl->isl_p); 834145510Sdarrenr 835145510Sdarrenr if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 836145510Sdarrenr (void) sprintf(t, "%s,%s -> ", 837145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), 838145510Sdarrenr portname(res, proto, (u_int)sl->isl_sport)); 839145510Sdarrenr t += strlen(t); 840145510Sdarrenr (void) sprintf(t, "%s,%s PR %s", 841145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 842145510Sdarrenr portname(res, proto, (u_int)sl->isl_dport), proto); 843145510Sdarrenr } else if (sl->isl_p == IPPROTO_ICMP) { 844145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 845145510Sdarrenr (u_32_t *)&sl->isl_src)); 846145510Sdarrenr t += strlen(t); 847145510Sdarrenr (void) sprintf(t, "%s PR icmp %d", 848145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 849145510Sdarrenr sl->isl_itype); 850145510Sdarrenr } else if (sl->isl_p == IPPROTO_ICMPV6) { 851145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 852145510Sdarrenr (u_32_t *)&sl->isl_src)); 853145510Sdarrenr t += strlen(t); 854145510Sdarrenr (void) sprintf(t, "%s PR icmpv6 %d", 855145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 856145510Sdarrenr sl->isl_itype); 857145510Sdarrenr } else { 858145510Sdarrenr (void) sprintf(t, "%s -> ", 859145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src)); 860145510Sdarrenr t += strlen(t); 861145510Sdarrenr (void) sprintf(t, "%s PR %s", 862145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 863145510Sdarrenr proto); 864145510Sdarrenr } 865145510Sdarrenr t += strlen(t); 866145510Sdarrenr if (sl->isl_tag != FR_NOLOGTAG) { 867145510Sdarrenr (void) sprintf(t, " tag %u", sl->isl_tag); 868145510Sdarrenr t += strlen(t); 869145510Sdarrenr } 870145510Sdarrenr if (sl->isl_type != ISL_NEW) { 871145510Sdarrenr sprintf(t, 872145510Sdarrenr#ifdef USE_QUAD_T 873145510Sdarrenr#ifdef PRId64 874145510Sdarrenr " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 875145510Sdarrenr " Pkts out %" PRId64 " Bytes out %" PRId64 876145510Sdarrenr " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 877145510Sdarrenr " Pkts out %" PRId64 " Bytes out %" PRId64, 878145510Sdarrenr#else 879145510Sdarrenr " 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", 880145510Sdarrenr#endif /* PRId64 */ 881145510Sdarrenr#else 882145510Sdarrenr " 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", 883145510Sdarrenr#endif 884145510Sdarrenr sl->isl_pkts[0], sl->isl_bytes[0], 885145510Sdarrenr sl->isl_pkts[1], sl->isl_bytes[1], 886145510Sdarrenr sl->isl_pkts[2], sl->isl_bytes[2], 887145510Sdarrenr sl->isl_pkts[3], sl->isl_bytes[3]); 888145510Sdarrenr 889145510Sdarrenr t += strlen(t); 890145510Sdarrenr } 891145510Sdarrenr 892145510Sdarrenr *t++ = '\n'; 893145510Sdarrenr *t++ = '\0'; 894145510Sdarrenr if (opts & OPT_SYSLOG) 895145510Sdarrenr syslog(LOG_INFO, "%s", line); 896145510Sdarrenr else 897145510Sdarrenr (void) fprintf(log, "%s", line); 898145510Sdarrenr} 899145510Sdarrenr 900145510Sdarrenr 901145510Sdarrenrstatic void print_log(logtype, log, buf, blen) 902145510SdarrenrFILE *log; 903145510Sdarrenrchar *buf; 904145510Sdarrenrint logtype, blen; 905145510Sdarrenr{ 906145510Sdarrenr iplog_t *ipl; 907145510Sdarrenr char *bp = NULL, *bpo = NULL; 908145510Sdarrenr int psize; 909145510Sdarrenr 910145510Sdarrenr while (blen > 0) { 911145510Sdarrenr ipl = (iplog_t *)buf; 912145510Sdarrenr if ((u_long)ipl & (sizeof(long)-1)) { 913145510Sdarrenr if (bp) 914145510Sdarrenr bpo = bp; 915145510Sdarrenr bp = (char *)malloc(blen); 916145510Sdarrenr bcopy((char *)ipl, bp, blen); 917145510Sdarrenr if (bpo) { 918145510Sdarrenr free(bpo); 919145510Sdarrenr bpo = NULL; 920145510Sdarrenr } 921145510Sdarrenr buf = bp; 922145510Sdarrenr continue; 923145510Sdarrenr } 924145510Sdarrenr 925145510Sdarrenr psize = ipl->ipl_dsize; 926145510Sdarrenr if (psize > blen) 927145510Sdarrenr break; 928145510Sdarrenr 929145510Sdarrenr if (binarylog) { 930145510Sdarrenr fwrite(buf, psize, 1, binarylog); 931145510Sdarrenr fflush(binarylog); 932145510Sdarrenr } 933145510Sdarrenr 934145510Sdarrenr if (logtype == IPL_LOGIPF) { 935145510Sdarrenr if (ipl->ipl_magic == IPL_MAGIC) 936145510Sdarrenr print_ipflog(log, buf, psize); 937145510Sdarrenr 938145510Sdarrenr } else if (logtype == IPL_LOGNAT) { 939145510Sdarrenr if (ipl->ipl_magic == IPL_MAGIC_NAT) 940145510Sdarrenr print_natlog(log, buf, psize); 941145510Sdarrenr 942145510Sdarrenr } else if (logtype == IPL_LOGSTATE) { 943145510Sdarrenr if (ipl->ipl_magic == IPL_MAGIC_STATE) 944145510Sdarrenr print_statelog(log, buf, psize); 945145510Sdarrenr } 946145510Sdarrenr 947145510Sdarrenr blen -= psize; 948145510Sdarrenr buf += psize; 949145510Sdarrenr } 950145510Sdarrenr if (bp) 951145510Sdarrenr free(bp); 952145510Sdarrenr return; 953145510Sdarrenr} 954145510Sdarrenr 955145510Sdarrenr 956145510Sdarrenrstatic void print_ipflog(log, buf, blen) 957145510SdarrenrFILE *log; 958145510Sdarrenrchar *buf; 959145510Sdarrenrint blen; 960145510Sdarrenr{ 961145510Sdarrenr tcphdr_t *tp; 962145510Sdarrenr struct icmp *ic; 963145510Sdarrenr struct icmp *icmp; 964145510Sdarrenr struct tm *tm; 965145510Sdarrenr char *t, *proto; 966145510Sdarrenr int i, v, lvl, res, len, off, plen, ipoff, defaction; 967145510Sdarrenr ip_t *ipc, *ip; 968145510Sdarrenr u_32_t *s, *d; 969145510Sdarrenr u_short hl, p; 970145510Sdarrenr ipflog_t *ipf; 971145510Sdarrenr iplog_t *ipl; 972145510Sdarrenr#ifdef USE_INET6 973145510Sdarrenr ip6_t *ip6; 974145510Sdarrenr#endif 975145510Sdarrenr 976145510Sdarrenr ipl = (iplog_t *)buf; 977145510Sdarrenr ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 978145510Sdarrenr ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 979145510Sdarrenr v = IP_V(ip); 980145510Sdarrenr res = (opts & OPT_RESOLVE) ? 1 : 0; 981145510Sdarrenr t = line; 982145510Sdarrenr *t = '\0'; 983145510Sdarrenr tm = get_tm(ipl->ipl_sec); 984145510Sdarrenr 985145510Sdarrenr len = sizeof(line); 986145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 987145510Sdarrenr (void) strftime(t, len, "%d/%m/%Y ", tm); 988145510Sdarrenr i = strlen(t); 989145510Sdarrenr len -= i; 990145510Sdarrenr t += i; 991145510Sdarrenr } 992145510Sdarrenr (void) strftime(t, len, "%T", tm); 993145510Sdarrenr t += strlen(t); 994145510Sdarrenr (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 995145510Sdarrenr t += strlen(t); 996145510Sdarrenr if (ipl->ipl_count > 1) { 997145510Sdarrenr (void) sprintf(t, "%dx ", ipl->ipl_count); 998145510Sdarrenr t += strlen(t); 999145510Sdarrenr } 1000145510Sdarrenr#if (defined(MENTAT) || \ 1001145510Sdarrenr (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 1002145510Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \ 1003145510Sdarrenr (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) 1004145510Sdarrenr { 1005145510Sdarrenr char ifname[sizeof(ipf->fl_ifname) + 1]; 1006145510Sdarrenr 1007145510Sdarrenr strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 1008145510Sdarrenr ifname[sizeof(ipf->fl_ifname)] = '\0'; 1009145510Sdarrenr (void) sprintf(t, "%s", ifname); 1010145510Sdarrenr t += strlen(t); 1011145510Sdarrenr# if defined(MENTAT) || defined(linux) 1012145510Sdarrenr if (ISALPHA(*(t - 1))) { 1013145510Sdarrenr sprintf(t, "%d", ipf->fl_unit); 1014145510Sdarrenr t += strlen(t); 1015145510Sdarrenr } 1016145510Sdarrenr# endif 1017145510Sdarrenr } 1018145510Sdarrenr#else 1019145510Sdarrenr for (len = 0; len < 3; len++) 1020145510Sdarrenr if (ipf->fl_ifname[len] == '\0') 1021145510Sdarrenr break; 1022145510Sdarrenr if (ipf->fl_ifname[len]) 1023145510Sdarrenr len++; 1024145510Sdarrenr (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); 1025145510Sdarrenr t += strlen(t); 1026145510Sdarrenr#endif 1027145510Sdarrenr#ifdef __sgi 1028145510Sdarrenr if ((ipf->fl_group[0] == 255) && (ipf->fl_group[1] == '\0')) 1029145510Sdarrenr#else 1030145510Sdarrenr if ((ipf->fl_group[0] == -1) && (ipf->fl_group[1] == '\0')) 1031145510Sdarrenr#endif 1032145510Sdarrenr strcat(t, " @-1:"); 1033145510Sdarrenr else if (ipf->fl_group[0] == '\0') 1034145510Sdarrenr (void) strcpy(t, " @0:"); 1035145510Sdarrenr else 1036145510Sdarrenr (void) sprintf(t, " @%s:", ipf->fl_group); 1037145510Sdarrenr t += strlen(t); 1038145510Sdarrenr if (ipf->fl_rule == 0xffffffff) 1039145510Sdarrenr strcat(t, "-1 "); 1040145510Sdarrenr else 1041145510Sdarrenr (void) sprintf(t, "%u ", ipf->fl_rule + 1); 1042145510Sdarrenr t += strlen(t); 1043145510Sdarrenr 1044145510Sdarrenr lvl = LOG_NOTICE; 1045145510Sdarrenr 1046145510Sdarrenr if (ipf->fl_lflags & FI_SHORT) { 1047145510Sdarrenr *t++ = 'S'; 1048145510Sdarrenr lvl = LOG_ERR; 1049145510Sdarrenr } 1050145510Sdarrenr 1051145510Sdarrenr if (FR_ISPASS(ipf->fl_flags)) { 1052145510Sdarrenr if (ipf->fl_flags & FR_LOGP) 1053145510Sdarrenr *t++ = 'p'; 1054145510Sdarrenr else 1055145510Sdarrenr *t++ = 'P'; 1056145510Sdarrenr } else if (FR_ISBLOCK(ipf->fl_flags)) { 1057145510Sdarrenr if (ipf->fl_flags & FR_LOGB) 1058145510Sdarrenr *t++ = 'b'; 1059145510Sdarrenr else 1060145510Sdarrenr *t++ = 'B'; 1061145510Sdarrenr lvl = LOG_WARNING; 1062145510Sdarrenr } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 1063145510Sdarrenr *t++ = 'L'; 1064145510Sdarrenr lvl = LOG_INFO; 1065145510Sdarrenr } else if (ipf->fl_flags & FF_LOGNOMATCH) { 1066145510Sdarrenr *t++ = 'n'; 1067145510Sdarrenr } else { 1068145510Sdarrenr *t++ = '?'; 1069145510Sdarrenr lvl = LOG_EMERG; 1070145510Sdarrenr } 1071145510Sdarrenr if (ipf->fl_loglevel != 0xffff) 1072145510Sdarrenr lvl = ipf->fl_loglevel; 1073145510Sdarrenr *t++ = ' '; 1074145510Sdarrenr *t = '\0'; 1075145510Sdarrenr 1076145510Sdarrenr if (v == 6) { 1077145510Sdarrenr#ifdef USE_INET6 1078145510Sdarrenr off = 0; 1079145510Sdarrenr ipoff = 0; 1080145510Sdarrenr hl = sizeof(ip6_t); 1081145510Sdarrenr ip6 = (ip6_t *)ip; 1082145510Sdarrenr p = (u_short)ip6->ip6_nxt; 1083145510Sdarrenr s = (u_32_t *)&ip6->ip6_src; 1084145510Sdarrenr d = (u_32_t *)&ip6->ip6_dst; 1085145510Sdarrenr plen = hl + ntohs(ip6->ip6_plen); 1086145510Sdarrenr#else 1087145510Sdarrenr sprintf(t, "ipv6"); 1088145510Sdarrenr goto printipflog; 1089145510Sdarrenr#endif 1090145510Sdarrenr } else if (v == 4) { 1091145510Sdarrenr hl = IP_HL(ip) << 2; 1092145510Sdarrenr ipoff = ip->ip_off; 1093145510Sdarrenr off = ipoff & IP_OFFMASK; 1094145510Sdarrenr p = (u_short)ip->ip_p; 1095145510Sdarrenr s = (u_32_t *)&ip->ip_src; 1096145510Sdarrenr d = (u_32_t *)&ip->ip_dst; 1097145510Sdarrenr plen = ip->ip_len; 1098145510Sdarrenr } else { 1099145510Sdarrenr goto printipflog; 1100145510Sdarrenr } 1101145510Sdarrenr proto = getproto(p); 1102145510Sdarrenr 1103145510Sdarrenr if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 1104145510Sdarrenr tp = (tcphdr_t *)((char *)ip + hl); 1105145510Sdarrenr if (!(ipf->fl_lflags & FI_SHORT)) { 1106145510Sdarrenr (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), 1107145510Sdarrenr portname(res, proto, (u_int)tp->th_sport)); 1108145510Sdarrenr t += strlen(t); 1109145510Sdarrenr (void) sprintf(t, "%s,%s PR %s len %hu %hu", 1110145510Sdarrenr hostname(res, v, d), 1111145510Sdarrenr portname(res, proto, (u_int)tp->th_dport), 1112145510Sdarrenr proto, hl, plen); 1113145510Sdarrenr t += strlen(t); 1114145510Sdarrenr 1115145510Sdarrenr if (p == IPPROTO_TCP) { 1116145510Sdarrenr *t++ = ' '; 1117145510Sdarrenr *t++ = '-'; 1118145510Sdarrenr for (i = 0; tcpfl[i].value; i++) 1119145510Sdarrenr if (tp->th_flags & tcpfl[i].value) 1120145510Sdarrenr *t++ = tcpfl[i].flag; 1121145510Sdarrenr if (opts & OPT_VERBOSE) { 1122145510Sdarrenr (void) sprintf(t, " %lu %lu %hu", 1123145510Sdarrenr (u_long)(ntohl(tp->th_seq)), 1124145510Sdarrenr (u_long)(ntohl(tp->th_ack)), 1125145510Sdarrenr ntohs(tp->th_win)); 1126145510Sdarrenr t += strlen(t); 1127145510Sdarrenr } 1128145510Sdarrenr } 1129145510Sdarrenr *t = '\0'; 1130145510Sdarrenr } else { 1131145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1132145510Sdarrenr t += strlen(t); 1133145510Sdarrenr (void) sprintf(t, "%s PR %s len %hu %hu", 1134145510Sdarrenr hostname(res, v, d), proto, hl, plen); 1135145510Sdarrenr } 1136145510Sdarrenr } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { 1137145510Sdarrenr ic = (struct icmp *)((char *)ip + hl); 1138145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1139145510Sdarrenr t += strlen(t); 1140145510Sdarrenr (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 1141145510Sdarrenr hostname(res, v, d), hl, plen, 1142145510Sdarrenr icmpname6(ic->icmp_type, ic->icmp_code)); 1143145510Sdarrenr } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { 1144145510Sdarrenr ic = (struct icmp *)((char *)ip + hl); 1145145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1146145510Sdarrenr t += strlen(t); 1147145510Sdarrenr (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", 1148145510Sdarrenr hostname(res, v, d), hl, plen, 1149145510Sdarrenr icmpname(ic->icmp_type, ic->icmp_code)); 1150145510Sdarrenr if (ic->icmp_type == ICMP_UNREACH || 1151145510Sdarrenr ic->icmp_type == ICMP_SOURCEQUENCH || 1152145510Sdarrenr ic->icmp_type == ICMP_PARAMPROB || 1153145510Sdarrenr ic->icmp_type == ICMP_REDIRECT || 1154145510Sdarrenr ic->icmp_type == ICMP_TIMXCEED) { 1155145510Sdarrenr ipc = &ic->icmp_ip; 1156145510Sdarrenr i = ntohs(ipc->ip_len); 1157145510Sdarrenr /* 1158145510Sdarrenr * XXX - try to guess endian of ip_len in ICMP 1159145510Sdarrenr * returned data. 1160145510Sdarrenr */ 1161145510Sdarrenr if (i > 1500) 1162145510Sdarrenr i = ipc->ip_len; 1163145510Sdarrenr ipoff = ntohs(ipc->ip_off); 1164145510Sdarrenr proto = getproto(ipc->ip_p); 1165145510Sdarrenr 1166145510Sdarrenr if (!(ipoff & IP_OFFMASK) && 1167145510Sdarrenr ((ipc->ip_p == IPPROTO_TCP) || 1168145510Sdarrenr (ipc->ip_p == IPPROTO_UDP))) { 1169145510Sdarrenr tp = (tcphdr_t *)((char *)ipc + hl); 1170145510Sdarrenr t += strlen(t); 1171145510Sdarrenr (void) sprintf(t, " for %s,%s -", 1172145510Sdarrenr HOSTNAME_V4(res, ipc->ip_src), 1173145510Sdarrenr portname(res, proto, 1174145510Sdarrenr (u_int)tp->th_sport)); 1175145510Sdarrenr t += strlen(t); 1176145510Sdarrenr (void) sprintf(t, " %s,%s PR %s len %hu %hu", 1177145510Sdarrenr HOSTNAME_V4(res, ipc->ip_dst), 1178145510Sdarrenr portname(res, proto, 1179145510Sdarrenr (u_int)tp->th_dport), 1180145510Sdarrenr proto, IP_HL(ipc) << 2, i); 1181145510Sdarrenr } else if (!(ipoff & IP_OFFMASK) && 1182145510Sdarrenr (ipc->ip_p == IPPROTO_ICMP)) { 1183145510Sdarrenr icmp = (icmphdr_t *)((char *)ipc + hl); 1184145510Sdarrenr 1185145510Sdarrenr t += strlen(t); 1186145510Sdarrenr (void) sprintf(t, " for %s -", 1187145510Sdarrenr HOSTNAME_V4(res, ipc->ip_src)); 1188145510Sdarrenr t += strlen(t); 1189145510Sdarrenr (void) sprintf(t, 1190145510Sdarrenr " %s PR icmp len %hu %hu icmp %d/%d", 1191145510Sdarrenr HOSTNAME_V4(res, ipc->ip_dst), 1192145510Sdarrenr IP_HL(ipc) << 2, i, 1193145510Sdarrenr icmp->icmp_type, icmp->icmp_code); 1194145510Sdarrenr } else { 1195145510Sdarrenr t += strlen(t); 1196145510Sdarrenr (void) sprintf(t, " for %s -", 1197145510Sdarrenr HOSTNAME_V4(res, ipc->ip_src)); 1198145510Sdarrenr t += strlen(t); 1199145510Sdarrenr (void) sprintf(t, " %s PR %s len %hu (%hu)", 1200145510Sdarrenr HOSTNAME_V4(res, ipc->ip_dst), proto, 1201145510Sdarrenr IP_HL(ipc) << 2, i); 1202145510Sdarrenr t += strlen(t); 1203145510Sdarrenr if (ipoff & IP_OFFMASK) { 1204145510Sdarrenr (void) sprintf(t, 1205145510Sdarrenr "(frag %d:%hu@%hu%s%s)", 1206145510Sdarrenr ntohs(ipc->ip_id), 1207145510Sdarrenr i - (IP_HL(ipc) << 2), 1208145510Sdarrenr (ipoff & IP_OFFMASK) << 3, 1209145510Sdarrenr ipoff & IP_MF ? "+" : "", 1210145510Sdarrenr ipoff & IP_DF ? "-" : ""); 1211145510Sdarrenr } 1212145510Sdarrenr } 1213145510Sdarrenr 1214145510Sdarrenr } 1215145510Sdarrenr } else { 1216145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1217145510Sdarrenr t += strlen(t); 1218145510Sdarrenr (void) sprintf(t, "%s PR %s len %hu (%hu)", 1219145510Sdarrenr hostname(res, v, d), proto, hl, plen); 1220145510Sdarrenr t += strlen(t); 1221145510Sdarrenr if (off & IP_OFFMASK) 1222145510Sdarrenr (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", 1223145510Sdarrenr ntohs(ip->ip_id), 1224145510Sdarrenr plen - hl, (off & IP_OFFMASK) << 3, 1225145510Sdarrenr ipoff & IP_MF ? "+" : "", 1226145510Sdarrenr ipoff & IP_DF ? "-" : ""); 1227145510Sdarrenr } 1228145510Sdarrenr t += strlen(t); 1229145510Sdarrenr 1230145510Sdarrenrprintipflog: 1231145510Sdarrenr if (ipf->fl_flags & FR_KEEPSTATE) { 1232145510Sdarrenr (void) strcpy(t, " K-S"); 1233145510Sdarrenr t += strlen(t); 1234145510Sdarrenr } 1235145510Sdarrenr 1236145510Sdarrenr if (ipf->fl_flags & FR_KEEPFRAG) { 1237145510Sdarrenr (void) strcpy(t, " K-F"); 1238145510Sdarrenr t += strlen(t); 1239145510Sdarrenr } 1240145510Sdarrenr 1241145510Sdarrenr if (ipf->fl_dir == 0) 1242145510Sdarrenr strcpy(t, " IN"); 1243145510Sdarrenr else if (ipf->fl_dir == 1) 1244145510Sdarrenr strcpy(t, " OUT"); 1245145510Sdarrenr t += strlen(t); 1246145510Sdarrenr if (ipf->fl_logtag != 0) { 1247145510Sdarrenr sprintf(t, " log-tag %d", ipf->fl_logtag); 1248145510Sdarrenr t += strlen(t); 1249145510Sdarrenr } 1250145510Sdarrenr if (ipf->fl_nattag.ipt_num[0] != 0) { 1251145510Sdarrenr strcpy(t, " nat-tag "); 1252145510Sdarrenr t += strlen(t); 1253145510Sdarrenr strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 1254145510Sdarrenr t += strlen(t); 1255145510Sdarrenr } 1256145510Sdarrenr if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 1257145510Sdarrenr strcpy(t, " low-ttl"); 1258145510Sdarrenr t += 8; 1259145510Sdarrenr } 1260145510Sdarrenr if ((ipf->fl_lflags & FI_OOW) != 0) { 1261145510Sdarrenr strcpy(t, " OOW"); 1262145510Sdarrenr t += 4; 1263145510Sdarrenr } 1264145510Sdarrenr if ((ipf->fl_lflags & FI_BAD) != 0) { 1265145510Sdarrenr strcpy(t, " bad"); 1266145510Sdarrenr t += 4; 1267145510Sdarrenr } 1268145510Sdarrenr if ((ipf->fl_lflags & FI_NATED) != 0) { 1269145510Sdarrenr strcpy(t, " NAT"); 1270145510Sdarrenr t += 4; 1271145510Sdarrenr } 1272145510Sdarrenr if ((ipf->fl_lflags & FI_BADNAT) != 0) { 1273145510Sdarrenr strcpy(t, " bad-NAT"); 1274145510Sdarrenr t += 8; 1275145510Sdarrenr } 1276145510Sdarrenr if ((ipf->fl_lflags & FI_BADSRC) != 0) { 1277145510Sdarrenr strcpy(t, " bad-src"); 1278145510Sdarrenr t += 8; 1279145510Sdarrenr } 1280145510Sdarrenr if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 1281145510Sdarrenr strcpy(t, " multicast"); 1282145510Sdarrenr t += 10; 1283145510Sdarrenr } 1284145510Sdarrenr if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 1285145510Sdarrenr strcpy(t, " broadcast"); 1286145510Sdarrenr t += 10; 1287145510Sdarrenr } 1288145510Sdarrenr if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 1289145510Sdarrenr FI_MBCAST) { 1290145510Sdarrenr strcpy(t, " mbcast"); 1291145510Sdarrenr t += 7; 1292145510Sdarrenr } 1293145510Sdarrenr *t++ = '\n'; 1294145510Sdarrenr *t++ = '\0'; 1295145510Sdarrenr defaction = 0; 1296145510Sdarrenr if (conf_file != NULL) 1297145510Sdarrenr defaction = check_action(buf, line, opts, lvl); 1298145510Sdarrenr if (defaction == 0) { 1299145510Sdarrenr if (opts & OPT_SYSLOG) 1300145510Sdarrenr syslog(lvl, "%s", line); 1301145510Sdarrenr else 1302145510Sdarrenr (void) fprintf(log, "%s", line); 1303145510Sdarrenr if (opts & OPT_HEXHDR) 1304145510Sdarrenr dumphex(log, opts, buf, 1305145510Sdarrenr sizeof(iplog_t) + sizeof(*ipf)); 1306145510Sdarrenr if (opts & OPT_HEXBODY) 1307145510Sdarrenr dumphex(log, opts, (char *)ip, 1308145510Sdarrenr ipf->fl_plen + ipf->fl_hlen); 1309145510Sdarrenr else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) 1310145510Sdarrenr dumphex(log, opts, (char *)ip + ipf->fl_hlen, 1311145510Sdarrenr ipf->fl_plen); 1312145510Sdarrenr } 1313145510Sdarrenr} 1314145510Sdarrenr 1315145510Sdarrenr 1316145510Sdarrenrstatic void usage(prog) 1317145510Sdarrenrchar *prog; 1318145510Sdarrenr{ 1319145510Sdarrenr fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog); 1320145510Sdarrenr exit(1); 1321145510Sdarrenr} 1322145510Sdarrenr 1323145510Sdarrenr 1324145510Sdarrenrstatic void write_pid(file) 1325145510Sdarrenrchar *file; 1326145510Sdarrenr{ 1327145510Sdarrenr FILE *fp = NULL; 1328145510Sdarrenr int fd; 1329145510Sdarrenr 1330145510Sdarrenr if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 1331145510Sdarrenr fp = fdopen(fd, "w"); 1332145510Sdarrenr if (fp == NULL) { 1333145510Sdarrenr close(fd); 1334145510Sdarrenr fprintf(stderr, 1335145510Sdarrenr "unable to open/create pid file: %s\n", file); 1336145510Sdarrenr return; 1337145510Sdarrenr } 1338145510Sdarrenr fprintf(fp, "%d", getpid()); 1339145510Sdarrenr fclose(fp); 1340145510Sdarrenr } 1341145510Sdarrenr} 1342145510Sdarrenr 1343145510Sdarrenr 1344145510Sdarrenrstatic void flushlogs(file, log) 1345145510Sdarrenrchar *file; 1346145510SdarrenrFILE *log; 1347145510Sdarrenr{ 1348145510Sdarrenr int fd, flushed = 0; 1349145510Sdarrenr 1350145510Sdarrenr if ((fd = open(file, O_RDWR)) == -1) { 1351145510Sdarrenr (void) fprintf(stderr, "%s: open: %s\n", 1352145510Sdarrenr file, STRERROR(errno)); 1353145510Sdarrenr exit(1); 1354145510Sdarrenr } 1355145510Sdarrenr 1356145510Sdarrenr if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 1357145510Sdarrenr printf("%d bytes flushed from log buffer\n", 1358145510Sdarrenr flushed); 1359145510Sdarrenr fflush(stdout); 1360145510Sdarrenr } else 1361145510Sdarrenr perror("SIOCIPFFB"); 1362145510Sdarrenr (void) close(fd); 1363145510Sdarrenr 1364145510Sdarrenr if (flushed) { 1365145510Sdarrenr if (opts & OPT_SYSLOG) 1366145510Sdarrenr syslog(LOG_INFO, "%d bytes flushed from log\n", 1367145510Sdarrenr flushed); 1368145510Sdarrenr else if (log != stdout) 1369145510Sdarrenr fprintf(log, "%d bytes flushed from log\n", flushed); 1370145510Sdarrenr } 1371145510Sdarrenr} 1372145510Sdarrenr 1373145510Sdarrenr 1374145510Sdarrenrstatic void logopts(turnon, options) 1375145510Sdarrenrint turnon; 1376145510Sdarrenrchar *options; 1377145510Sdarrenr{ 1378145510Sdarrenr int flags = 0; 1379145510Sdarrenr char *s; 1380145510Sdarrenr 1381145510Sdarrenr for (s = options; *s; s++) 1382145510Sdarrenr { 1383145510Sdarrenr switch (*s) 1384145510Sdarrenr { 1385145510Sdarrenr case 'N' : 1386145510Sdarrenr flags |= OPT_NAT; 1387145510Sdarrenr break; 1388145510Sdarrenr case 'S' : 1389145510Sdarrenr flags |= OPT_STATE; 1390145510Sdarrenr break; 1391145510Sdarrenr case 'I' : 1392145510Sdarrenr flags |= OPT_FILTER; 1393145510Sdarrenr break; 1394145510Sdarrenr default : 1395145510Sdarrenr fprintf(stderr, "Unknown log option %c\n", *s); 1396145510Sdarrenr exit(1); 1397145510Sdarrenr } 1398145510Sdarrenr } 1399145510Sdarrenr 1400145510Sdarrenr if (turnon) 1401145510Sdarrenr opts |= flags; 1402145510Sdarrenr else 1403145510Sdarrenr opts &= ~(flags); 1404145510Sdarrenr} 1405145510Sdarrenr 1406145510Sdarrenr 1407145510Sdarrenrint main(argc, argv) 1408145510Sdarrenrint argc; 1409145510Sdarrenrchar *argv[]; 1410145510Sdarrenr{ 1411145510Sdarrenr struct stat sb; 1412145510Sdarrenr FILE *log = stdout; 1413145510Sdarrenr FILE *fp; 1414145510Sdarrenr int fd[3], doread, n, i; 1415145510Sdarrenr int tr, nr, regular[3], c; 1416145510Sdarrenr int fdt[3], devices = 0, make_daemon = 0; 1417145510Sdarrenr char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; 1418145510Sdarrenr extern int optind; 1419145510Sdarrenr extern char *optarg; 1420145510Sdarrenr 1421145510Sdarrenr fd[0] = fd[1] = fd[2] = -1; 1422145510Sdarrenr fdt[0] = fdt[1] = fdt[2] = -1; 1423145510Sdarrenr iplfile[0] = IPL_NAME; 1424145510Sdarrenr iplfile[1] = IPNAT_NAME; 1425145510Sdarrenr iplfile[2] = IPSTATE_NAME; 1426145510Sdarrenr 1427145510Sdarrenr while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1) 1428145510Sdarrenr switch (c) 1429145510Sdarrenr { 1430145510Sdarrenr case 'a' : 1431145510Sdarrenr opts |= OPT_LOGALL; 1432145510Sdarrenr fdt[0] = IPL_LOGIPF; 1433145510Sdarrenr fdt[1] = IPL_LOGNAT; 1434145510Sdarrenr fdt[2] = IPL_LOGSTATE; 1435145510Sdarrenr break; 1436145510Sdarrenr case 'b' : 1437145510Sdarrenr opts |= OPT_LOGBODY; 1438145510Sdarrenr break; 1439145510Sdarrenr case 'B' : 1440145510Sdarrenr binarylogfile = optarg; 1441145510Sdarrenr binarylog = fopen(optarg, "a"); 1442145510Sdarrenr break; 1443145510Sdarrenr case 'C' : 1444145510Sdarrenr conf_file = optarg; 1445145510Sdarrenr break; 1446145510Sdarrenr case 'D' : 1447145510Sdarrenr make_daemon = 1; 1448145510Sdarrenr break; 1449145510Sdarrenr case 'f' : case 'I' : 1450145510Sdarrenr opts |= OPT_FILTER; 1451145510Sdarrenr fdt[0] = IPL_LOGIPF; 1452145510Sdarrenr iplfile[0] = optarg; 1453145510Sdarrenr break; 1454145510Sdarrenr case 'F' : 1455145510Sdarrenr flushlogs(iplfile[0], log); 1456145510Sdarrenr flushlogs(iplfile[1], log); 1457145510Sdarrenr flushlogs(iplfile[2], log); 1458145510Sdarrenr break; 1459145510Sdarrenr case 'n' : 1460145510Sdarrenr opts |= OPT_RESOLVE; 1461145510Sdarrenr break; 1462145510Sdarrenr case 'N' : 1463145510Sdarrenr opts |= OPT_NAT; 1464145510Sdarrenr fdt[1] = IPL_LOGNAT; 1465145510Sdarrenr iplfile[1] = optarg; 1466145510Sdarrenr break; 1467145510Sdarrenr case 'o' : case 'O' : 1468145510Sdarrenr logopts(c == 'o', optarg); 1469145510Sdarrenr fdt[0] = fdt[1] = fdt[2] = -1; 1470145510Sdarrenr if (opts & OPT_FILTER) 1471145510Sdarrenr fdt[0] = IPL_LOGIPF; 1472145510Sdarrenr if (opts & OPT_NAT) 1473145510Sdarrenr fdt[1] = IPL_LOGNAT; 1474145510Sdarrenr if (opts & OPT_STATE) 1475145510Sdarrenr fdt[2] = IPL_LOGSTATE; 1476145510Sdarrenr break; 1477145510Sdarrenr case 'p' : 1478145510Sdarrenr opts |= OPT_PORTNUM; 1479145510Sdarrenr break; 1480145510Sdarrenr case 'P' : 1481145510Sdarrenr pidfile = optarg; 1482145510Sdarrenr break; 1483145510Sdarrenr case 's' : 1484145510Sdarrenr s = strrchr(argv[0], '/'); 1485145510Sdarrenr if (s == NULL) 1486145510Sdarrenr s = argv[0]; 1487145510Sdarrenr else 1488145510Sdarrenr s++; 1489145510Sdarrenr openlog(s, LOG_NDELAY|LOG_PID, LOGFAC); 1490145510Sdarrenr s = NULL; 1491145510Sdarrenr opts |= OPT_SYSLOG; 1492145510Sdarrenr log = NULL; 1493145510Sdarrenr break; 1494145510Sdarrenr case 'S' : 1495145510Sdarrenr opts |= OPT_STATE; 1496145510Sdarrenr fdt[2] = IPL_LOGSTATE; 1497145510Sdarrenr iplfile[2] = optarg; 1498145510Sdarrenr break; 1499145510Sdarrenr case 't' : 1500145510Sdarrenr opts |= OPT_TAIL; 1501145510Sdarrenr break; 1502145510Sdarrenr case 'v' : 1503145510Sdarrenr opts |= OPT_VERBOSE; 1504145510Sdarrenr break; 1505145510Sdarrenr case 'x' : 1506145510Sdarrenr opts |= OPT_HEXBODY; 1507145510Sdarrenr break; 1508145510Sdarrenr case 'X' : 1509145510Sdarrenr opts |= OPT_HEXHDR; 1510145510Sdarrenr break; 1511145510Sdarrenr default : 1512145510Sdarrenr case 'h' : 1513145510Sdarrenr case '?' : 1514145510Sdarrenr usage(argv[0]); 1515145510Sdarrenr } 1516145510Sdarrenr 1517145510Sdarrenr init_tabs(); 1518145510Sdarrenr if (conf_file) 1519145510Sdarrenr if (load_config(conf_file) == -1) 1520145510Sdarrenr exit(1); 1521145510Sdarrenr 1522145510Sdarrenr /* 1523145510Sdarrenr * Default action is to only open the filter log file. 1524145510Sdarrenr */ 1525145510Sdarrenr if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) 1526145510Sdarrenr fdt[0] = IPL_LOGIPF; 1527145510Sdarrenr 1528145510Sdarrenr for (i = 0; i < 3; i++) { 1529145510Sdarrenr if (fdt[i] == -1) 1530145510Sdarrenr continue; 1531145510Sdarrenr if (!strcmp(iplfile[i], "-")) 1532145510Sdarrenr fd[i] = 0; 1533145510Sdarrenr else { 1534145510Sdarrenr if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { 1535145510Sdarrenr (void) fprintf(stderr, 1536145510Sdarrenr "%s: open: %s\n", iplfile[i], 1537145510Sdarrenr STRERROR(errno)); 1538145510Sdarrenr exit(1); 1539145510Sdarrenr /* NOTREACHED */ 1540145510Sdarrenr } 1541145510Sdarrenr if (fstat(fd[i], &sb) == -1) { 1542145510Sdarrenr (void) fprintf(stderr, "%d: fstat: %s\n", 1543145510Sdarrenr fd[i], STRERROR(errno)); 1544145510Sdarrenr exit(1); 1545145510Sdarrenr /* NOTREACHED */ 1546145510Sdarrenr } 1547145510Sdarrenr if (!(regular[i] = !S_ISCHR(sb.st_mode))) 1548145510Sdarrenr devices++; 1549145510Sdarrenr } 1550145510Sdarrenr } 1551145510Sdarrenr 1552145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 1553145510Sdarrenr logfile = argv[optind]; 1554145510Sdarrenr log = logfile ? fopen(logfile, "a") : stdout; 1555145510Sdarrenr if (log == NULL) { 1556145510Sdarrenr (void) fprintf(stderr, "%s: fopen: %s\n", 1557145510Sdarrenr argv[optind], STRERROR(errno)); 1558145510Sdarrenr exit(1); 1559145510Sdarrenr /* NOTREACHED */ 1560145510Sdarrenr } 1561145510Sdarrenr setvbuf(log, NULL, _IONBF, 0); 1562145510Sdarrenr } else 1563145510Sdarrenr log = NULL; 1564145510Sdarrenr 1565145510Sdarrenr if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { 1566145510Sdarrenr#if BSD >= 199306 1567145510Sdarrenr daemon(0, !(opts & OPT_SYSLOG)); 1568145510Sdarrenr#else 1569145510Sdarrenr int pid; 1570145510Sdarrenr if ((pid = fork()) > 0) 1571145510Sdarrenr exit(0); 1572145510Sdarrenr if (pid < 0) { 1573145510Sdarrenr (void) fprintf(stderr, "%s: fork() failed: %s\n", 1574145510Sdarrenr argv[0], STRERROR(errno)); 1575145510Sdarrenr exit(1); 1576145510Sdarrenr /* NOTREACHED */ 1577145510Sdarrenr } 1578145510Sdarrenr setsid(); 1579145510Sdarrenr if ((opts & OPT_SYSLOG)) 1580145510Sdarrenr close(2); 1581145510Sdarrenr#endif /* !BSD */ 1582145510Sdarrenr close(0); 1583145510Sdarrenr close(1); 1584145510Sdarrenr } 1585145510Sdarrenr write_pid(pidfile); 1586145510Sdarrenr 1587145510Sdarrenr signal(SIGHUP, handlehup); 1588145510Sdarrenr 1589145510Sdarrenr for (doread = 1; doread; ) { 1590145510Sdarrenr nr = 0; 1591145510Sdarrenr 1592145510Sdarrenr for (i = 0; i < 3; i++) { 1593145510Sdarrenr tr = 0; 1594145510Sdarrenr if (fdt[i] == -1) 1595145510Sdarrenr continue; 1596145510Sdarrenr if (!regular[i]) { 1597145510Sdarrenr if (ioctl(fd[i], FIONREAD, &tr) == -1) { 1598145510Sdarrenr if (opts & OPT_SYSLOG) 1599145510Sdarrenr syslog(LOG_CRIT, 1600145510Sdarrenr "ioctl(FIONREAD): %m"); 1601145510Sdarrenr else 1602145510Sdarrenr perror("ioctl(FIONREAD)"); 1603145510Sdarrenr exit(1); 1604145510Sdarrenr /* NOTREACHED */ 1605145510Sdarrenr } 1606145510Sdarrenr } else { 1607145510Sdarrenr tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); 1608145510Sdarrenr if (!tr && !(opts & OPT_TAIL)) 1609145510Sdarrenr doread = 0; 1610145510Sdarrenr } 1611145510Sdarrenr if (!tr) 1612145510Sdarrenr continue; 1613145510Sdarrenr nr += tr; 1614145510Sdarrenr 1615145510Sdarrenr tr = read_log(fd[i], &n, buf, sizeof(buf)); 1616145510Sdarrenr if (donehup) { 1617145510Sdarrenr if (logfile && (fp = fopen(logfile, "a"))) { 1618145510Sdarrenr fclose(log); 1619145510Sdarrenr log = fp; 1620145510Sdarrenr } 1621145510Sdarrenr if (binarylogfile && (fp = fopen(binarylogfile, "a"))) { 1622145510Sdarrenr fclose(binarylog); 1623145510Sdarrenr binarylog = fp; 1624145510Sdarrenr } 1625145510Sdarrenr init_tabs(); 1626145510Sdarrenr if (conf_file != NULL) 1627145510Sdarrenr load_config(conf_file); 1628145510Sdarrenr donehup = 0; 1629145510Sdarrenr } 1630145510Sdarrenr 1631145510Sdarrenr switch (tr) 1632145510Sdarrenr { 1633145510Sdarrenr case -1 : 1634145510Sdarrenr if (opts & OPT_SYSLOG) 1635145510Sdarrenr syslog(LOG_CRIT, "read: %m\n"); 1636145510Sdarrenr else 1637145510Sdarrenr perror("read"); 1638145510Sdarrenr doread = 0; 1639145510Sdarrenr break; 1640145510Sdarrenr case 1 : 1641145510Sdarrenr if (opts & OPT_SYSLOG) 1642145510Sdarrenr syslog(LOG_CRIT, "aborting logging\n"); 1643145510Sdarrenr else 1644145510Sdarrenr fprintf(log, "aborting logging\n"); 1645145510Sdarrenr doread = 0; 1646145510Sdarrenr break; 1647145510Sdarrenr case 2 : 1648145510Sdarrenr break; 1649145510Sdarrenr case 0 : 1650145510Sdarrenr if (n > 0) { 1651145510Sdarrenr print_log(fdt[i], log, buf, n); 1652145510Sdarrenr if (!(opts & OPT_SYSLOG)) 1653145510Sdarrenr fflush(log); 1654145510Sdarrenr } 1655145510Sdarrenr break; 1656145510Sdarrenr } 1657145510Sdarrenr } 1658145510Sdarrenr if (!nr && ((opts & OPT_TAIL) || devices)) 1659145510Sdarrenr sleep(1); 1660145510Sdarrenr } 1661145510Sdarrenr return(0); 1662145510Sdarrenr /* NOTREACHED */ 1663145510Sdarrenr} 1664