1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr/* 4170268Sdarrenr * Copyright (C) 2001-2006 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"; 81172776Sdarrenrstatic const char rcsid[] = "@(#)$Id: ipmon.c,v 1.33.2.20 2007/09/20 12:51:56 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 194161357Sguidoint logfac = LOGFAC; 195145510Sdarrenr 196145510Sdarrenr 197145510Sdarrenrstatic icmp_subtype_t icmpunreachnames[] = { 198145510Sdarrenr { ICMP_UNREACH_NET, "net" }, 199145510Sdarrenr { ICMP_UNREACH_HOST, "host" }, 200145510Sdarrenr { ICMP_UNREACH_PROTOCOL, "protocol" }, 201145510Sdarrenr { ICMP_UNREACH_PORT, "port" }, 202145510Sdarrenr { ICMP_UNREACH_NEEDFRAG, "needfrag" }, 203145510Sdarrenr { ICMP_UNREACH_SRCFAIL, "srcfail" }, 204145510Sdarrenr { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, 205145510Sdarrenr { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, 206145510Sdarrenr { ICMP_UNREACH_NET, "isolated" }, 207145510Sdarrenr { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, 208145510Sdarrenr { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, 209145510Sdarrenr { ICMP_UNREACH_TOSNET, "tosnet" }, 210145510Sdarrenr { ICMP_UNREACH_TOSHOST, "toshost" }, 211145510Sdarrenr { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, 212145510Sdarrenr { -2, NULL } 213145510Sdarrenr}; 214145510Sdarrenr 215145510Sdarrenrstatic icmp_subtype_t redirectnames[] = { 216145510Sdarrenr { ICMP_REDIRECT_NET, "net" }, 217145510Sdarrenr { ICMP_REDIRECT_HOST, "host" }, 218145510Sdarrenr { ICMP_REDIRECT_TOSNET, "tosnet" }, 219145510Sdarrenr { ICMP_REDIRECT_TOSHOST, "toshost" }, 220145510Sdarrenr { -2, NULL } 221145510Sdarrenr}; 222145510Sdarrenr 223145510Sdarrenrstatic icmp_subtype_t timxceednames[] = { 224145510Sdarrenr { ICMP_TIMXCEED_INTRANS, "transit" }, 225145510Sdarrenr { ICMP_TIMXCEED_REASS, "reassem" }, 226145510Sdarrenr { -2, NULL } 227145510Sdarrenr}; 228145510Sdarrenr 229145510Sdarrenrstatic icmp_subtype_t paramnames[] = { 230145510Sdarrenr { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, 231145510Sdarrenr { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, 232145510Sdarrenr { ICMP_PARAMPROB_LENGTH, "length" }, 233145510Sdarrenr { -2, NULL } 234145510Sdarrenr}; 235145510Sdarrenr 236145510Sdarrenrstatic icmp_type_t icmptypes[] = { 237145510Sdarrenr { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, 238145510Sdarrenr { -1, NULL, 0, NULL }, 239145510Sdarrenr { -1, NULL, 0, NULL }, 240145510Sdarrenr { ICMP_UNREACH, icmpunreachnames, 241145510Sdarrenr IST_SZ(icmpunreachnames),"unreach" }, 242145510Sdarrenr { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, 243145510Sdarrenr { ICMP_REDIRECT, redirectnames, 244145510Sdarrenr IST_SZ(redirectnames), "redirect" }, 245145510Sdarrenr { -1, NULL, 0, NULL }, 246145510Sdarrenr { -1, NULL, 0, NULL }, 247145510Sdarrenr { ICMP_ECHO, NULL, 0, "echo" }, 248145510Sdarrenr { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, 249145510Sdarrenr { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, 250145510Sdarrenr { ICMP_TIMXCEED, timxceednames, 251145510Sdarrenr IST_SZ(timxceednames), "timxceed" }, 252145510Sdarrenr { ICMP_PARAMPROB, paramnames, 253145510Sdarrenr IST_SZ(paramnames), "paramprob" }, 254145510Sdarrenr { ICMP_TSTAMP, NULL, 0, "timestamp" }, 255145510Sdarrenr { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, 256145510Sdarrenr { ICMP_IREQ, NULL, 0, "inforeq" }, 257145510Sdarrenr { ICMP_IREQREPLY, NULL, 0, "inforeply" }, 258145510Sdarrenr { ICMP_MASKREQ, NULL, 0, "maskreq" }, 259145510Sdarrenr { ICMP_MASKREPLY, NULL, 0, "maskreply" }, 260145510Sdarrenr { -2, NULL, 0, NULL } 261145510Sdarrenr}; 262145510Sdarrenr 263145510Sdarrenrstatic icmp_subtype_t icmpredirect6[] = { 264145510Sdarrenr { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, 265145510Sdarrenr { ICMP6_DST_UNREACH_ADMIN, "admin" }, 266145510Sdarrenr { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, 267145510Sdarrenr { ICMP6_DST_UNREACH_ADDR, "address" }, 268145510Sdarrenr { ICMP6_DST_UNREACH_NOPORT, "noport" }, 269145510Sdarrenr { -2, NULL } 270145510Sdarrenr}; 271145510Sdarrenr 272145510Sdarrenrstatic icmp_subtype_t icmptimexceed6[] = { 273145510Sdarrenr { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, 274145510Sdarrenr { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, 275145510Sdarrenr { -2, NULL } 276145510Sdarrenr}; 277145510Sdarrenr 278145510Sdarrenrstatic icmp_subtype_t icmpparamprob6[] = { 279145510Sdarrenr { ICMP6_PARAMPROB_HEADER, "header" }, 280145510Sdarrenr { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, 281145510Sdarrenr { ICMP6_PARAMPROB_OPTION, "option" }, 282145510Sdarrenr { -2, NULL } 283145510Sdarrenr}; 284145510Sdarrenr 285145510Sdarrenrstatic icmp_subtype_t icmpquerysubject6[] = { 286145510Sdarrenr { ICMP6_NI_SUBJ_IPV6, "ipv6" }, 287145510Sdarrenr { ICMP6_NI_SUBJ_FQDN, "fqdn" }, 288145510Sdarrenr { ICMP6_NI_SUBJ_IPV4, "ipv4" }, 289145510Sdarrenr { -2, NULL }, 290145510Sdarrenr}; 291145510Sdarrenr 292145510Sdarrenrstatic icmp_subtype_t icmpnodeinfo6[] = { 293145510Sdarrenr { ICMP6_NI_SUCCESS, "success" }, 294145510Sdarrenr { ICMP6_NI_REFUSED, "refused" }, 295145510Sdarrenr { ICMP6_NI_UNKNOWN, "unknown" }, 296145510Sdarrenr { -2, NULL } 297145510Sdarrenr}; 298145510Sdarrenr 299145510Sdarrenrstatic icmp_subtype_t icmprenumber6[] = { 300145510Sdarrenr { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, 301145510Sdarrenr { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, 302145510Sdarrenr { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, 303145510Sdarrenr { -2, NULL } 304145510Sdarrenr}; 305145510Sdarrenr 306145510Sdarrenrstatic icmp_type_t icmptypes6[] = { 307145510Sdarrenr { 0, NULL, 0, NULL }, 308145510Sdarrenr { ICMP6_DST_UNREACH, icmpredirect6, 309145510Sdarrenr IST_SZ(icmpredirect6), "unreach" }, 310145510Sdarrenr { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, 311145510Sdarrenr { ICMP6_TIME_EXCEEDED, icmptimexceed6, 312145510Sdarrenr IST_SZ(icmptimexceed6), "timxceed" }, 313145510Sdarrenr { ICMP6_PARAM_PROB, icmpparamprob6, 314145510Sdarrenr IST_SZ(icmpparamprob6), "paramprob" }, 315145510Sdarrenr { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, 316145510Sdarrenr { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, 317145510Sdarrenr { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, 318145510Sdarrenr IST_SZ(icmpquerysubject6), "groupmemberquery" }, 319145510Sdarrenr { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, 320145510Sdarrenr { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, 321145510Sdarrenr { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, 322145510Sdarrenr { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, 323145510Sdarrenr { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, 324145510Sdarrenr { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, 325145510Sdarrenr { ND_REDIRECT, NULL, 0, "redirect" }, 326145510Sdarrenr { ICMP6_ROUTER_RENUMBERING, icmprenumber6, 327145510Sdarrenr IST_SZ(icmprenumber6), "routerrenumber" }, 328145510Sdarrenr { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, 329145510Sdarrenr { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, 330145510Sdarrenr { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, 331145510Sdarrenr { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, 332145510Sdarrenr { ICMP6_NI_QUERY, icmpnodeinfo6, 333145510Sdarrenr IST_SZ(icmpnodeinfo6), "nodeinforequest" }, 334145510Sdarrenr { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, 335145510Sdarrenr { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, 336145510Sdarrenr { MLD6_MTRACE, NULL, 0, "mtracerequest" }, 337145510Sdarrenr { -2, NULL, 0, NULL } 338145510Sdarrenr}; 339145510Sdarrenr 340145510Sdarrenrstatic icmp_subtype_t *find_icmpsubtype(type, table, tablesz) 341145510Sdarrenrint type; 342145510Sdarrenricmp_subtype_t *table; 343145510Sdarrenrsize_t tablesz; 344145510Sdarrenr{ 345145510Sdarrenr icmp_subtype_t *ist; 346145510Sdarrenr int i; 347145510Sdarrenr 348145510Sdarrenr if (tablesz < 2) 349145510Sdarrenr return NULL; 350145510Sdarrenr 351145510Sdarrenr if ((type < 0) || (type > table[tablesz - 2].ist_val)) 352145510Sdarrenr return NULL; 353145510Sdarrenr 354145510Sdarrenr i = type; 355145510Sdarrenr if (table[type].ist_val == type) 356145510Sdarrenr return table + type; 357145510Sdarrenr 358145510Sdarrenr for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) 359145510Sdarrenr if (ist->ist_val == type) 360145510Sdarrenr return ist; 361145510Sdarrenr return NULL; 362145510Sdarrenr} 363145510Sdarrenr 364145510Sdarrenr 365145510Sdarrenrstatic icmp_type_t *find_icmptype(type, table, tablesz) 366145510Sdarrenrint type; 367145510Sdarrenricmp_type_t *table; 368145510Sdarrenrsize_t tablesz; 369145510Sdarrenr{ 370145510Sdarrenr icmp_type_t *it; 371145510Sdarrenr int i; 372145510Sdarrenr 373145510Sdarrenr if (tablesz < 2) 374145510Sdarrenr return NULL; 375145510Sdarrenr 376145510Sdarrenr if ((type < 0) || (type > table[tablesz - 2].it_val)) 377145510Sdarrenr return NULL; 378145510Sdarrenr 379145510Sdarrenr i = type; 380145510Sdarrenr if (table[type].it_val == type) 381145510Sdarrenr return table + type; 382145510Sdarrenr 383145510Sdarrenr for (i = 0, it = table; it->it_val != -2; i++, it++) 384145510Sdarrenr if (it->it_val == type) 385145510Sdarrenr return it; 386145510Sdarrenr return NULL; 387145510Sdarrenr} 388145510Sdarrenr 389145510Sdarrenr 390145510Sdarrenrstatic void handlehup(sig) 391145510Sdarrenrint sig; 392145510Sdarrenr{ 393145510Sdarrenr signal(SIGHUP, handlehup); 394145510Sdarrenr donehup = 1; 395145510Sdarrenr} 396145510Sdarrenr 397145510Sdarrenr 398145510Sdarrenrstatic void init_tabs() 399145510Sdarrenr{ 400145510Sdarrenr struct protoent *p; 401145510Sdarrenr struct servent *s; 402145510Sdarrenr char *name, **tab; 403145510Sdarrenr int port, i; 404145510Sdarrenr 405145510Sdarrenr if (protocols != NULL) { 406145510Sdarrenr for (i = 0; i < 256; i++) 407145510Sdarrenr if (protocols[i] != NULL) { 408145510Sdarrenr free(protocols[i]); 409145510Sdarrenr protocols[i] = NULL; 410145510Sdarrenr } 411145510Sdarrenr free(protocols); 412145510Sdarrenr protocols = NULL; 413145510Sdarrenr } 414145510Sdarrenr protocols = (char **)malloc(256 * sizeof(*protocols)); 415145510Sdarrenr if (protocols != NULL) { 416145510Sdarrenr bzero((char *)protocols, 256 * sizeof(*protocols)); 417145510Sdarrenr 418145510Sdarrenr setprotoent(1); 419145510Sdarrenr while ((p = getprotoent()) != NULL) 420145510Sdarrenr if (p->p_proto >= 0 && p->p_proto <= 255 && 421145510Sdarrenr p->p_name != NULL && protocols[p->p_proto] == NULL) 422145510Sdarrenr protocols[p->p_proto] = strdup(p->p_name); 423145510Sdarrenr endprotoent(); 424153881Sguido#if defined(_AIX51) 425153881Sguido if (protocols[0]) 426153881Sguido free(protocols[0]); 427153881Sguido if (protocols[252]) 428153881Sguido free(protocols[252]); 429153881Sguido protocols[0] = "ip"; 430153881Sguido protocols[252] = NULL; 431153881Sguido#endif 432145510Sdarrenr } 433145510Sdarrenr 434145510Sdarrenr if (udp_ports != NULL) { 435145510Sdarrenr for (i = 0; i < 65536; i++) 436145510Sdarrenr if (udp_ports[i] != NULL) { 437145510Sdarrenr free(udp_ports[i]); 438145510Sdarrenr udp_ports[i] = NULL; 439145510Sdarrenr } 440145510Sdarrenr free(udp_ports); 441145510Sdarrenr udp_ports = NULL; 442145510Sdarrenr } 443145510Sdarrenr udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 444145510Sdarrenr if (udp_ports != NULL) 445145510Sdarrenr bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 446145510Sdarrenr 447145510Sdarrenr if (tcp_ports != NULL) { 448145510Sdarrenr for (i = 0; i < 65536; i++) 449145510Sdarrenr if (tcp_ports[i] != NULL) { 450145510Sdarrenr free(tcp_ports[i]); 451145510Sdarrenr tcp_ports[i] = NULL; 452145510Sdarrenr } 453145510Sdarrenr free(tcp_ports); 454145510Sdarrenr tcp_ports = NULL; 455145510Sdarrenr } 456145510Sdarrenr tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 457145510Sdarrenr if (tcp_ports != NULL) 458145510Sdarrenr bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 459145510Sdarrenr 460145510Sdarrenr setservent(1); 461145510Sdarrenr while ((s = getservent()) != NULL) { 462145510Sdarrenr if (s->s_proto == NULL) 463145510Sdarrenr continue; 464145510Sdarrenr else if (!strcmp(s->s_proto, "tcp")) { 465145510Sdarrenr port = ntohs(s->s_port); 466145510Sdarrenr name = s->s_name; 467145510Sdarrenr tab = tcp_ports; 468145510Sdarrenr } else if (!strcmp(s->s_proto, "udp")) { 469145510Sdarrenr port = ntohs(s->s_port); 470145510Sdarrenr name = s->s_name; 471145510Sdarrenr tab = udp_ports; 472145510Sdarrenr } else 473145510Sdarrenr continue; 474145510Sdarrenr if ((port < 0 || port > 65535) || (name == NULL)) 475145510Sdarrenr continue; 476145510Sdarrenr if (tab != NULL) 477145510Sdarrenr tab[port] = strdup(name); 478145510Sdarrenr } 479145510Sdarrenr endservent(); 480145510Sdarrenr} 481145510Sdarrenr 482145510Sdarrenr 483145510Sdarrenrstatic char *getproto(p) 484145510Sdarrenru_int p; 485145510Sdarrenr{ 486145510Sdarrenr static char pnum[4]; 487145510Sdarrenr char *s; 488145510Sdarrenr 489145510Sdarrenr p &= 0xff; 490145510Sdarrenr s = protocols ? protocols[p] : NULL; 491145510Sdarrenr if (s == NULL) { 492145510Sdarrenr sprintf(pnum, "%u", p); 493145510Sdarrenr s = pnum; 494145510Sdarrenr } 495145510Sdarrenr return s; 496145510Sdarrenr} 497145510Sdarrenr 498145510Sdarrenr 499145510Sdarrenrstatic int read_log(fd, lenp, buf, bufsize) 500145510Sdarrenrint fd, bufsize, *lenp; 501145510Sdarrenrchar *buf; 502145510Sdarrenr{ 503145510Sdarrenr int nr; 504145510Sdarrenr 505145510Sdarrenr nr = read(fd, buf, bufsize); 506145510Sdarrenr if (!nr) 507145510Sdarrenr return 2; 508145510Sdarrenr if ((nr < 0) && (errno != EINTR)) 509145510Sdarrenr return -1; 510145510Sdarrenr *lenp = nr; 511145510Sdarrenr return 0; 512145510Sdarrenr} 513145510Sdarrenr 514145510Sdarrenr 515145510Sdarrenrchar *hostname(res, v, ip) 516145510Sdarrenrint res, v; 517145510Sdarrenru_32_t *ip; 518145510Sdarrenr{ 519145510Sdarrenr# define MAX_INETA 16 520145510Sdarrenr static char hname[MAXHOSTNAMELEN + MAX_INETA + 3]; 521145510Sdarrenr#ifdef USE_INET6 522145510Sdarrenr static char hostbuf[MAXHOSTNAMELEN+1]; 523145510Sdarrenr#endif 524145510Sdarrenr struct hostent *hp; 525145510Sdarrenr struct in_addr ipa; 526145510Sdarrenr 527145510Sdarrenr if (v == 4) { 528145510Sdarrenr ipa.s_addr = *ip; 529145510Sdarrenr if (!res) 530145510Sdarrenr return inet_ntoa(ipa); 531145510Sdarrenr hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET); 532145510Sdarrenr if (!hp) 533145510Sdarrenr return inet_ntoa(ipa); 534145510Sdarrenr sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, 535145510Sdarrenr inet_ntoa(ipa)); 536145510Sdarrenr return hname; 537145510Sdarrenr } 538145510Sdarrenr#ifdef USE_INET6 539145510Sdarrenr (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); 540145510Sdarrenr hostbuf[MAXHOSTNAMELEN] = '\0'; 541145510Sdarrenr return hostbuf; 542145510Sdarrenr#else 543145510Sdarrenr return "IPv6"; 544145510Sdarrenr#endif 545145510Sdarrenr} 546145510Sdarrenr 547145510Sdarrenr 548145510Sdarrenrchar *portname(res, proto, port) 549145510Sdarrenrint res; 550145510Sdarrenrchar *proto; 551145510Sdarrenru_int port; 552145510Sdarrenr{ 553145510Sdarrenr static char pname[8]; 554145510Sdarrenr char *s; 555145510Sdarrenr 556145510Sdarrenr port = ntohs(port); 557145510Sdarrenr port &= 0xffff; 558145510Sdarrenr (void) sprintf(pname, "%u", port); 559145510Sdarrenr if (!res || (opts & OPT_PORTNUM)) 560145510Sdarrenr return pname; 561145510Sdarrenr s = NULL; 562145510Sdarrenr if (!strcmp(proto, "tcp")) 563145510Sdarrenr s = tcp_ports[port]; 564145510Sdarrenr else if (!strcmp(proto, "udp")) 565145510Sdarrenr s = udp_ports[port]; 566145510Sdarrenr if (s == NULL) 567145510Sdarrenr s = pname; 568145510Sdarrenr return s; 569145510Sdarrenr} 570145510Sdarrenr 571145510Sdarrenr 572145510Sdarrenrstatic char *icmpname(type, code) 573145510Sdarrenru_int type; 574145510Sdarrenru_int code; 575145510Sdarrenr{ 576145510Sdarrenr static char name[80]; 577145510Sdarrenr icmp_subtype_t *ist; 578145510Sdarrenr icmp_type_t *it; 579145510Sdarrenr char *s; 580145510Sdarrenr 581145510Sdarrenr s = NULL; 582145510Sdarrenr it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it)); 583145510Sdarrenr if (it != NULL) 584145510Sdarrenr s = it->it_name; 585145510Sdarrenr 586145510Sdarrenr if (s == NULL) 587145510Sdarrenr sprintf(name, "icmptype(%d)/", type); 588145510Sdarrenr else 589145510Sdarrenr sprintf(name, "%s/", s); 590145510Sdarrenr 591145510Sdarrenr ist = NULL; 592145510Sdarrenr if (it != NULL && it->it_subtable != NULL) 593145510Sdarrenr ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 594145510Sdarrenr 595145510Sdarrenr if (ist != NULL && ist->ist_name != NULL) 596145510Sdarrenr strcat(name, ist->ist_name); 597145510Sdarrenr else 598145510Sdarrenr sprintf(name + strlen(name), "%d", code); 599145510Sdarrenr 600145510Sdarrenr return name; 601145510Sdarrenr} 602145510Sdarrenr 603145510Sdarrenrstatic char *icmpname6(type, code) 604145510Sdarrenru_int type; 605145510Sdarrenru_int code; 606145510Sdarrenr{ 607145510Sdarrenr static char name[80]; 608145510Sdarrenr icmp_subtype_t *ist; 609145510Sdarrenr icmp_type_t *it; 610145510Sdarrenr char *s; 611145510Sdarrenr 612145510Sdarrenr s = NULL; 613145510Sdarrenr it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 614145510Sdarrenr if (it != NULL) 615145510Sdarrenr s = it->it_name; 616145510Sdarrenr 617145510Sdarrenr if (s == NULL) 618145510Sdarrenr sprintf(name, "icmpv6type(%d)/", type); 619145510Sdarrenr else 620145510Sdarrenr sprintf(name, "%s/", s); 621145510Sdarrenr 622145510Sdarrenr ist = NULL; 623145510Sdarrenr if (it != NULL && it->it_subtable != NULL) 624145510Sdarrenr ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 625145510Sdarrenr 626145510Sdarrenr if (ist != NULL && ist->ist_name != NULL) 627145510Sdarrenr strcat(name, ist->ist_name); 628145510Sdarrenr else 629145510Sdarrenr sprintf(name + strlen(name), "%d", code); 630145510Sdarrenr 631145510Sdarrenr return name; 632145510Sdarrenr} 633145510Sdarrenr 634145510Sdarrenr 635145510Sdarrenrvoid dumphex(log, dopts, buf, len) 636145510SdarrenrFILE *log; 637145510Sdarrenrint dopts; 638145510Sdarrenrchar *buf; 639145510Sdarrenrint len; 640145510Sdarrenr{ 641145510Sdarrenr char hline[80]; 642145510Sdarrenr int i, j, k; 643145510Sdarrenr u_char *s = (u_char *)buf, *t = (u_char *)hline; 644145510Sdarrenr 645145510Sdarrenr if (buf == NULL || len == 0) 646145510Sdarrenr return; 647145510Sdarrenr 648145510Sdarrenr *hline = '\0'; 649145510Sdarrenr 650145510Sdarrenr for (i = len, j = 0; i; i--, j++, s++) { 651145510Sdarrenr if (j && !(j & 0xf)) { 652145510Sdarrenr *t++ = '\n'; 653145510Sdarrenr *t = '\0'; 654161357Sguido if ((dopts & OPT_SYSLOG)) 655161357Sguido syslog(LOG_INFO, "%s", hline); 656161357Sguido else if (log != NULL) 657145510Sdarrenr fputs(hline, log); 658145510Sdarrenr t = (u_char *)hline; 659145510Sdarrenr *t = '\0'; 660145510Sdarrenr } 661145510Sdarrenr sprintf((char *)t, "%02x", *s & 0xff); 662145510Sdarrenr t += 2; 663145510Sdarrenr if (!((j + 1) & 0xf)) { 664145510Sdarrenr s -= 15; 665145510Sdarrenr sprintf((char *)t, " "); 666145510Sdarrenr t += 8; 667145510Sdarrenr for (k = 16; k; k--, s++) 668145510Sdarrenr *t++ = (ISPRINT(*s) ? *s : '.'); 669145510Sdarrenr s--; 670145510Sdarrenr } 671145510Sdarrenr 672145510Sdarrenr if ((j + 1) & 0xf) 673145510Sdarrenr *t++ = ' ';; 674145510Sdarrenr } 675145510Sdarrenr 676145510Sdarrenr if (j & 0xf) { 677145510Sdarrenr for (k = 16 - (j & 0xf); k; k--) { 678145510Sdarrenr *t++ = ' '; 679145510Sdarrenr *t++ = ' '; 680145510Sdarrenr *t++ = ' '; 681145510Sdarrenr } 682145510Sdarrenr sprintf((char *)t, " "); 683145510Sdarrenr t += 7; 684145510Sdarrenr s -= j & 0xf; 685145510Sdarrenr for (k = j & 0xf; k; k--, s++) 686145510Sdarrenr *t++ = (ISPRINT(*s) ? *s : '.'); 687145510Sdarrenr *t++ = '\n'; 688145510Sdarrenr *t = '\0'; 689145510Sdarrenr } 690161357Sguido if ((dopts & OPT_SYSLOG) != 0) 691161357Sguido syslog(LOG_INFO, "%s", hline); 692161357Sguido else if (log != NULL) { 693145510Sdarrenr fputs(hline, log); 694145510Sdarrenr fflush(log); 695161357Sguido } 696145510Sdarrenr} 697145510Sdarrenr 698145510Sdarrenr 699145510Sdarrenrstatic struct tm *get_tm(sec) 700145510Sdarrenr#ifdef __hpux 701145510Sdarrenru_32_t sec; 702145510Sdarrenr#else 703145510Sdarrenrtime_t sec; 704145510Sdarrenr#endif 705145510Sdarrenr{ 706145510Sdarrenr struct tm *tm; 707145510Sdarrenr time_t t; 708145510Sdarrenr 709145510Sdarrenr t = sec; 710145510Sdarrenr tm = localtime(&t); 711145510Sdarrenr return tm; 712145510Sdarrenr} 713145510Sdarrenr 714145510Sdarrenrstatic void print_natlog(log, buf, blen) 715145510SdarrenrFILE *log; 716145510Sdarrenrchar *buf; 717145510Sdarrenrint blen; 718145510Sdarrenr{ 719145510Sdarrenr struct natlog *nl; 720145510Sdarrenr iplog_t *ipl = (iplog_t *)buf; 721145510Sdarrenr char *t = line; 722145510Sdarrenr struct tm *tm; 723145510Sdarrenr int res, i, len; 724145510Sdarrenr char *proto; 725145510Sdarrenr 726145510Sdarrenr nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 727145510Sdarrenr res = (opts & OPT_RESOLVE) ? 1 : 0; 728145510Sdarrenr tm = get_tm(ipl->ipl_sec); 729145510Sdarrenr len = sizeof(line); 730145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 731145510Sdarrenr (void) strftime(t, len, "%d/%m/%Y ", tm); 732145510Sdarrenr i = strlen(t); 733145510Sdarrenr len -= i; 734145510Sdarrenr t += i; 735145510Sdarrenr } 736145510Sdarrenr (void) strftime(t, len, "%T", tm); 737145510Sdarrenr t += strlen(t); 738145510Sdarrenr (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1); 739145510Sdarrenr t += strlen(t); 740145510Sdarrenr 741145510Sdarrenr if (nl->nl_type == NL_NEWMAP) 742145510Sdarrenr strcpy(t, "NAT:MAP "); 743145510Sdarrenr else if (nl->nl_type == NL_NEWRDR) 744145510Sdarrenr strcpy(t, "NAT:RDR "); 745145510Sdarrenr else if (nl->nl_type == NL_FLUSH) 746145510Sdarrenr strcpy(t, "NAT:FLUSH "); 747145510Sdarrenr else if (nl->nl_type == NL_EXPIRE) 748145510Sdarrenr strcpy(t, "NAT:EXPIRE "); 749145510Sdarrenr else if (nl->nl_type == NL_NEWBIMAP) 750145510Sdarrenr strcpy(t, "NAT:BIMAP "); 751145510Sdarrenr else if (nl->nl_type == NL_NEWBLOCK) 752145510Sdarrenr strcpy(t, "NAT:MAPBLOCK "); 753145510Sdarrenr else if (nl->nl_type == NL_CLONE) 754145510Sdarrenr strcpy(t, "NAT:CLONE "); 755172776Sdarrenr else if (nl->nl_type == NL_DESTROY) 756172776Sdarrenr strcpy(t, "NAT:DESTROY "); 757145510Sdarrenr else 758145510Sdarrenr sprintf(t, "Type: %d ", nl->nl_type); 759145510Sdarrenr t += strlen(t); 760145510Sdarrenr 761145510Sdarrenr proto = getproto(nl->nl_p); 762145510Sdarrenr 763145510Sdarrenr (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), 764145510Sdarrenr portname(res, proto, (u_int)nl->nl_inport)); 765145510Sdarrenr t += strlen(t); 766145510Sdarrenr (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), 767145510Sdarrenr portname(res, proto, (u_int)nl->nl_outport)); 768145510Sdarrenr t += strlen(t); 769172776Sdarrenr (void) sprintf(t, "[%s,%s PR %s]", HOSTNAME_V4(res, nl->nl_origip), 770172776Sdarrenr portname(res, proto, (u_int)nl->nl_origport), 771172776Sdarrenr getproto(nl->nl_p)); 772145510Sdarrenr t += strlen(t); 773145510Sdarrenr if (nl->nl_type == NL_EXPIRE) { 774145510Sdarrenr#ifdef USE_QUAD_T 775145510Sdarrenr (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 776145510Sdarrenr (long long)nl->nl_pkts[0], 777145510Sdarrenr (long long)nl->nl_pkts[1], 778145510Sdarrenr (long long)nl->nl_bytes[0], 779145510Sdarrenr (long long)nl->nl_bytes[1]); 780145510Sdarrenr#else 781145510Sdarrenr (void) sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 782145510Sdarrenr nl->nl_pkts[0], nl->nl_pkts[1], 783145510Sdarrenr nl->nl_bytes[0], nl->nl_bytes[1]); 784145510Sdarrenr#endif 785145510Sdarrenr t += strlen(t); 786145510Sdarrenr } 787145510Sdarrenr 788145510Sdarrenr *t++ = '\n'; 789145510Sdarrenr *t++ = '\0'; 790145510Sdarrenr if (opts & OPT_SYSLOG) 791145510Sdarrenr syslog(LOG_INFO, "%s", line); 792161357Sguido else if (log != NULL) 793145510Sdarrenr (void) fprintf(log, "%s", line); 794145510Sdarrenr} 795145510Sdarrenr 796145510Sdarrenr 797145510Sdarrenrstatic void print_statelog(log, buf, blen) 798145510SdarrenrFILE *log; 799145510Sdarrenrchar *buf; 800145510Sdarrenrint blen; 801145510Sdarrenr{ 802145510Sdarrenr struct ipslog *sl; 803145510Sdarrenr iplog_t *ipl = (iplog_t *)buf; 804145510Sdarrenr char *t = line, *proto; 805145510Sdarrenr struct tm *tm; 806145510Sdarrenr int res, i, len; 807145510Sdarrenr 808145510Sdarrenr sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 809145510Sdarrenr res = (opts & OPT_RESOLVE) ? 1 : 0; 810145510Sdarrenr tm = get_tm(ipl->ipl_sec); 811145510Sdarrenr len = sizeof(line); 812145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 813145510Sdarrenr (void) strftime(t, len, "%d/%m/%Y ", tm); 814145510Sdarrenr i = strlen(t); 815145510Sdarrenr len -= i; 816145510Sdarrenr t += i; 817145510Sdarrenr } 818145510Sdarrenr (void) strftime(t, len, "%T", tm); 819145510Sdarrenr t += strlen(t); 820145510Sdarrenr (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 821145510Sdarrenr t += strlen(t); 822145510Sdarrenr 823170268Sdarrenr switch (sl->isl_type) 824170268Sdarrenr { 825170268Sdarrenr case ISL_NEW : 826145510Sdarrenr strcpy(t, "STATE:NEW "); 827170268Sdarrenr break; 828170268Sdarrenr 829170268Sdarrenr case ISL_CLONE : 830145510Sdarrenr strcpy(t, "STATE:CLONED "); 831170268Sdarrenr break; 832170268Sdarrenr 833170268Sdarrenr case ISL_EXPIRE : 834145510Sdarrenr if ((sl->isl_p == IPPROTO_TCP) && 835145510Sdarrenr (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 836145510Sdarrenr sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 837145510Sdarrenr strcpy(t, "STATE:CLOSE "); 838145510Sdarrenr else 839145510Sdarrenr strcpy(t, "STATE:EXPIRE "); 840170268Sdarrenr break; 841170268Sdarrenr 842170268Sdarrenr case ISL_FLUSH : 843145510Sdarrenr strcpy(t, "STATE:FLUSH "); 844170268Sdarrenr break; 845170268Sdarrenr 846170268Sdarrenr case ISL_INTERMEDIATE : 847145510Sdarrenr strcpy(t, "STATE:INTERMEDIATE "); 848170268Sdarrenr break; 849170268Sdarrenr 850170268Sdarrenr case ISL_REMOVE : 851145510Sdarrenr strcpy(t, "STATE:REMOVE "); 852170268Sdarrenr break; 853170268Sdarrenr 854170268Sdarrenr case ISL_KILLED : 855145510Sdarrenr strcpy(t, "STATE:KILLED "); 856170268Sdarrenr break; 857170268Sdarrenr 858170268Sdarrenr case ISL_UNLOAD : 859170268Sdarrenr strcpy(t, "STATE:UNLOAD "); 860170268Sdarrenr break; 861170268Sdarrenr 862170268Sdarrenr default : 863145510Sdarrenr sprintf(t, "Type: %d ", sl->isl_type); 864170268Sdarrenr break; 865170268Sdarrenr } 866145510Sdarrenr t += strlen(t); 867145510Sdarrenr 868145510Sdarrenr proto = getproto(sl->isl_p); 869145510Sdarrenr 870145510Sdarrenr if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 871145510Sdarrenr (void) sprintf(t, "%s,%s -> ", 872145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), 873145510Sdarrenr portname(res, proto, (u_int)sl->isl_sport)); 874145510Sdarrenr t += strlen(t); 875145510Sdarrenr (void) sprintf(t, "%s,%s PR %s", 876145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 877145510Sdarrenr portname(res, proto, (u_int)sl->isl_dport), proto); 878145510Sdarrenr } else if (sl->isl_p == IPPROTO_ICMP) { 879145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 880145510Sdarrenr (u_32_t *)&sl->isl_src)); 881145510Sdarrenr t += strlen(t); 882145510Sdarrenr (void) sprintf(t, "%s PR icmp %d", 883145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 884145510Sdarrenr sl->isl_itype); 885145510Sdarrenr } else if (sl->isl_p == IPPROTO_ICMPV6) { 886145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 887145510Sdarrenr (u_32_t *)&sl->isl_src)); 888145510Sdarrenr t += strlen(t); 889145510Sdarrenr (void) sprintf(t, "%s PR icmpv6 %d", 890145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 891145510Sdarrenr sl->isl_itype); 892145510Sdarrenr } else { 893145510Sdarrenr (void) sprintf(t, "%s -> ", 894145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src)); 895145510Sdarrenr t += strlen(t); 896145510Sdarrenr (void) sprintf(t, "%s PR %s", 897145510Sdarrenr hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 898145510Sdarrenr proto); 899145510Sdarrenr } 900145510Sdarrenr t += strlen(t); 901145510Sdarrenr if (sl->isl_tag != FR_NOLOGTAG) { 902145510Sdarrenr (void) sprintf(t, " tag %u", sl->isl_tag); 903145510Sdarrenr t += strlen(t); 904145510Sdarrenr } 905145510Sdarrenr if (sl->isl_type != ISL_NEW) { 906145510Sdarrenr sprintf(t, 907145510Sdarrenr#ifdef USE_QUAD_T 908145510Sdarrenr#ifdef PRId64 909145510Sdarrenr " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 910145510Sdarrenr " Pkts out %" PRId64 " Bytes out %" PRId64 911145510Sdarrenr " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 912145510Sdarrenr " Pkts out %" PRId64 " Bytes out %" PRId64, 913145510Sdarrenr#else 914145510Sdarrenr " 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", 915145510Sdarrenr#endif /* PRId64 */ 916145510Sdarrenr#else 917145510Sdarrenr " 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", 918145510Sdarrenr#endif 919145510Sdarrenr sl->isl_pkts[0], sl->isl_bytes[0], 920145510Sdarrenr sl->isl_pkts[1], sl->isl_bytes[1], 921145510Sdarrenr sl->isl_pkts[2], sl->isl_bytes[2], 922145510Sdarrenr sl->isl_pkts[3], sl->isl_bytes[3]); 923145510Sdarrenr 924145510Sdarrenr t += strlen(t); 925145510Sdarrenr } 926145510Sdarrenr 927145510Sdarrenr *t++ = '\n'; 928145510Sdarrenr *t++ = '\0'; 929145510Sdarrenr if (opts & OPT_SYSLOG) 930145510Sdarrenr syslog(LOG_INFO, "%s", line); 931161357Sguido else if (log != NULL) 932145510Sdarrenr (void) fprintf(log, "%s", line); 933145510Sdarrenr} 934145510Sdarrenr 935145510Sdarrenr 936145510Sdarrenrstatic void print_log(logtype, log, buf, blen) 937145510SdarrenrFILE *log; 938145510Sdarrenrchar *buf; 939145510Sdarrenrint logtype, blen; 940145510Sdarrenr{ 941145510Sdarrenr iplog_t *ipl; 942145510Sdarrenr char *bp = NULL, *bpo = NULL; 943145510Sdarrenr int psize; 944145510Sdarrenr 945145510Sdarrenr while (blen > 0) { 946145510Sdarrenr ipl = (iplog_t *)buf; 947145510Sdarrenr if ((u_long)ipl & (sizeof(long)-1)) { 948145510Sdarrenr if (bp) 949145510Sdarrenr bpo = bp; 950145510Sdarrenr bp = (char *)malloc(blen); 951145510Sdarrenr bcopy((char *)ipl, bp, blen); 952145510Sdarrenr if (bpo) { 953145510Sdarrenr free(bpo); 954145510Sdarrenr bpo = NULL; 955145510Sdarrenr } 956145510Sdarrenr buf = bp; 957145510Sdarrenr continue; 958145510Sdarrenr } 959145510Sdarrenr 960145510Sdarrenr psize = ipl->ipl_dsize; 961145510Sdarrenr if (psize > blen) 962145510Sdarrenr break; 963145510Sdarrenr 964145510Sdarrenr if (binarylog) { 965145510Sdarrenr fwrite(buf, psize, 1, binarylog); 966145510Sdarrenr fflush(binarylog); 967145510Sdarrenr } 968145510Sdarrenr 969145510Sdarrenr if (logtype == IPL_LOGIPF) { 970145510Sdarrenr if (ipl->ipl_magic == IPL_MAGIC) 971145510Sdarrenr print_ipflog(log, buf, psize); 972145510Sdarrenr 973145510Sdarrenr } else if (logtype == IPL_LOGNAT) { 974145510Sdarrenr if (ipl->ipl_magic == IPL_MAGIC_NAT) 975145510Sdarrenr print_natlog(log, buf, psize); 976145510Sdarrenr 977145510Sdarrenr } else if (logtype == IPL_LOGSTATE) { 978145510Sdarrenr if (ipl->ipl_magic == IPL_MAGIC_STATE) 979145510Sdarrenr print_statelog(log, buf, psize); 980145510Sdarrenr } 981145510Sdarrenr 982145510Sdarrenr blen -= psize; 983145510Sdarrenr buf += psize; 984145510Sdarrenr } 985145510Sdarrenr if (bp) 986145510Sdarrenr free(bp); 987145510Sdarrenr return; 988145510Sdarrenr} 989145510Sdarrenr 990145510Sdarrenr 991145510Sdarrenrstatic void print_ipflog(log, buf, blen) 992145510SdarrenrFILE *log; 993145510Sdarrenrchar *buf; 994145510Sdarrenrint blen; 995145510Sdarrenr{ 996145510Sdarrenr tcphdr_t *tp; 997145510Sdarrenr struct icmp *ic; 998145510Sdarrenr struct icmp *icmp; 999145510Sdarrenr struct tm *tm; 1000145510Sdarrenr char *t, *proto; 1001145510Sdarrenr int i, v, lvl, res, len, off, plen, ipoff, defaction; 1002145510Sdarrenr ip_t *ipc, *ip; 1003145510Sdarrenr u_32_t *s, *d; 1004145510Sdarrenr u_short hl, p; 1005145510Sdarrenr ipflog_t *ipf; 1006145510Sdarrenr iplog_t *ipl; 1007145510Sdarrenr#ifdef USE_INET6 1008172776Sdarrenr struct ip6_ext *ehp; 1009172776Sdarrenr u_short ehl; 1010145510Sdarrenr ip6_t *ip6; 1011172776Sdarrenr int go; 1012145510Sdarrenr#endif 1013145510Sdarrenr 1014145510Sdarrenr ipl = (iplog_t *)buf; 1015145510Sdarrenr ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 1016145510Sdarrenr ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 1017145510Sdarrenr v = IP_V(ip); 1018145510Sdarrenr res = (opts & OPT_RESOLVE) ? 1 : 0; 1019145510Sdarrenr t = line; 1020145510Sdarrenr *t = '\0'; 1021145510Sdarrenr tm = get_tm(ipl->ipl_sec); 1022145510Sdarrenr 1023145510Sdarrenr len = sizeof(line); 1024145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 1025145510Sdarrenr (void) strftime(t, len, "%d/%m/%Y ", tm); 1026145510Sdarrenr i = strlen(t); 1027145510Sdarrenr len -= i; 1028145510Sdarrenr t += i; 1029145510Sdarrenr } 1030145510Sdarrenr (void) strftime(t, len, "%T", tm); 1031145510Sdarrenr t += strlen(t); 1032145510Sdarrenr (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 1033145510Sdarrenr t += strlen(t); 1034145510Sdarrenr if (ipl->ipl_count > 1) { 1035145510Sdarrenr (void) sprintf(t, "%dx ", ipl->ipl_count); 1036145510Sdarrenr t += strlen(t); 1037145510Sdarrenr } 1038145510Sdarrenr#if (defined(MENTAT) || \ 1039145510Sdarrenr (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 1040145510Sdarrenr (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \ 1041145510Sdarrenr (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) 1042145510Sdarrenr { 1043145510Sdarrenr char ifname[sizeof(ipf->fl_ifname) + 1]; 1044145510Sdarrenr 1045145510Sdarrenr strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 1046145510Sdarrenr ifname[sizeof(ipf->fl_ifname)] = '\0'; 1047145510Sdarrenr (void) sprintf(t, "%s", ifname); 1048145510Sdarrenr t += strlen(t); 1049145510Sdarrenr# if defined(MENTAT) || defined(linux) 1050145510Sdarrenr if (ISALPHA(*(t - 1))) { 1051145510Sdarrenr sprintf(t, "%d", ipf->fl_unit); 1052145510Sdarrenr t += strlen(t); 1053145510Sdarrenr } 1054145510Sdarrenr# endif 1055145510Sdarrenr } 1056145510Sdarrenr#else 1057145510Sdarrenr for (len = 0; len < 3; len++) 1058145510Sdarrenr if (ipf->fl_ifname[len] == '\0') 1059145510Sdarrenr break; 1060145510Sdarrenr if (ipf->fl_ifname[len]) 1061145510Sdarrenr len++; 1062145510Sdarrenr (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); 1063145510Sdarrenr t += strlen(t); 1064145510Sdarrenr#endif 1065161357Sguido if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) 1066145510Sdarrenr strcat(t, " @-1:"); 1067145510Sdarrenr else if (ipf->fl_group[0] == '\0') 1068145510Sdarrenr (void) strcpy(t, " @0:"); 1069145510Sdarrenr else 1070145510Sdarrenr (void) sprintf(t, " @%s:", ipf->fl_group); 1071145510Sdarrenr t += strlen(t); 1072145510Sdarrenr if (ipf->fl_rule == 0xffffffff) 1073145510Sdarrenr strcat(t, "-1 "); 1074145510Sdarrenr else 1075145510Sdarrenr (void) sprintf(t, "%u ", ipf->fl_rule + 1); 1076145510Sdarrenr t += strlen(t); 1077145510Sdarrenr 1078145510Sdarrenr lvl = LOG_NOTICE; 1079145510Sdarrenr 1080145510Sdarrenr if (ipf->fl_lflags & FI_SHORT) { 1081145510Sdarrenr *t++ = 'S'; 1082145510Sdarrenr lvl = LOG_ERR; 1083145510Sdarrenr } 1084145510Sdarrenr 1085145510Sdarrenr if (FR_ISPASS(ipf->fl_flags)) { 1086145510Sdarrenr if (ipf->fl_flags & FR_LOGP) 1087145510Sdarrenr *t++ = 'p'; 1088145510Sdarrenr else 1089145510Sdarrenr *t++ = 'P'; 1090145510Sdarrenr } else if (FR_ISBLOCK(ipf->fl_flags)) { 1091145510Sdarrenr if (ipf->fl_flags & FR_LOGB) 1092145510Sdarrenr *t++ = 'b'; 1093145510Sdarrenr else 1094145510Sdarrenr *t++ = 'B'; 1095145510Sdarrenr lvl = LOG_WARNING; 1096145510Sdarrenr } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 1097145510Sdarrenr *t++ = 'L'; 1098145510Sdarrenr lvl = LOG_INFO; 1099145510Sdarrenr } else if (ipf->fl_flags & FF_LOGNOMATCH) { 1100145510Sdarrenr *t++ = 'n'; 1101145510Sdarrenr } else { 1102145510Sdarrenr *t++ = '?'; 1103145510Sdarrenr lvl = LOG_EMERG; 1104145510Sdarrenr } 1105145510Sdarrenr if (ipf->fl_loglevel != 0xffff) 1106145510Sdarrenr lvl = ipf->fl_loglevel; 1107145510Sdarrenr *t++ = ' '; 1108145510Sdarrenr *t = '\0'; 1109145510Sdarrenr 1110145510Sdarrenr if (v == 6) { 1111145510Sdarrenr#ifdef USE_INET6 1112145510Sdarrenr off = 0; 1113145510Sdarrenr ipoff = 0; 1114145510Sdarrenr hl = sizeof(ip6_t); 1115145510Sdarrenr ip6 = (ip6_t *)ip; 1116145510Sdarrenr p = (u_short)ip6->ip6_nxt; 1117145510Sdarrenr s = (u_32_t *)&ip6->ip6_src; 1118145510Sdarrenr d = (u_32_t *)&ip6->ip6_dst; 1119145510Sdarrenr plen = hl + ntohs(ip6->ip6_plen); 1120172776Sdarrenr go = 1; 1121172776Sdarrenr ehp = (struct ip6_ext *)((char *)ip6 + hl); 1122172776Sdarrenr while (go == 1) { 1123172776Sdarrenr switch (p) 1124172776Sdarrenr { 1125172776Sdarrenr case IPPROTO_HOPOPTS : 1126172776Sdarrenr case IPPROTO_MOBILITY : 1127172776Sdarrenr case IPPROTO_DSTOPTS : 1128172776Sdarrenr case IPPROTO_ROUTING : 1129172776Sdarrenr case IPPROTO_AH : 1130172776Sdarrenr p = ehp->ip6e_nxt; 1131172776Sdarrenr ehl = 8 + (ehp->ip6e_len << 3); 1132172776Sdarrenr hl += ehl; 1133172776Sdarrenr ehp = (struct ip6_ext *)((char *)ehp + ehl); 1134172776Sdarrenr break; 1135172776Sdarrenr case IPPROTO_FRAGMENT : 1136172776Sdarrenr hl += sizeof(struct ip6_frag); 1137172776Sdarrenr /* FALLTHROUGH */ 1138172776Sdarrenr default : 1139172776Sdarrenr go = 0; 1140172776Sdarrenr break; 1141172776Sdarrenr } 1142172776Sdarrenr } 1143145510Sdarrenr#else 1144145510Sdarrenr sprintf(t, "ipv6"); 1145145510Sdarrenr goto printipflog; 1146145510Sdarrenr#endif 1147145510Sdarrenr } else if (v == 4) { 1148145510Sdarrenr hl = IP_HL(ip) << 2; 1149145510Sdarrenr ipoff = ip->ip_off; 1150145510Sdarrenr off = ipoff & IP_OFFMASK; 1151145510Sdarrenr p = (u_short)ip->ip_p; 1152145510Sdarrenr s = (u_32_t *)&ip->ip_src; 1153145510Sdarrenr d = (u_32_t *)&ip->ip_dst; 1154145510Sdarrenr plen = ip->ip_len; 1155145510Sdarrenr } else { 1156145510Sdarrenr goto printipflog; 1157145510Sdarrenr } 1158145510Sdarrenr proto = getproto(p); 1159145510Sdarrenr 1160145510Sdarrenr if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 1161145510Sdarrenr tp = (tcphdr_t *)((char *)ip + hl); 1162145510Sdarrenr if (!(ipf->fl_lflags & FI_SHORT)) { 1163145510Sdarrenr (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), 1164145510Sdarrenr portname(res, proto, (u_int)tp->th_sport)); 1165145510Sdarrenr t += strlen(t); 1166145510Sdarrenr (void) sprintf(t, "%s,%s PR %s len %hu %hu", 1167145510Sdarrenr hostname(res, v, d), 1168145510Sdarrenr portname(res, proto, (u_int)tp->th_dport), 1169145510Sdarrenr proto, hl, plen); 1170145510Sdarrenr t += strlen(t); 1171145510Sdarrenr 1172145510Sdarrenr if (p == IPPROTO_TCP) { 1173145510Sdarrenr *t++ = ' '; 1174145510Sdarrenr *t++ = '-'; 1175145510Sdarrenr for (i = 0; tcpfl[i].value; i++) 1176145510Sdarrenr if (tp->th_flags & tcpfl[i].value) 1177145510Sdarrenr *t++ = tcpfl[i].flag; 1178145510Sdarrenr if (opts & OPT_VERBOSE) { 1179145510Sdarrenr (void) sprintf(t, " %lu %lu %hu", 1180145510Sdarrenr (u_long)(ntohl(tp->th_seq)), 1181145510Sdarrenr (u_long)(ntohl(tp->th_ack)), 1182145510Sdarrenr ntohs(tp->th_win)); 1183145510Sdarrenr t += strlen(t); 1184145510Sdarrenr } 1185145510Sdarrenr } 1186145510Sdarrenr *t = '\0'; 1187145510Sdarrenr } else { 1188145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1189145510Sdarrenr t += strlen(t); 1190145510Sdarrenr (void) sprintf(t, "%s PR %s len %hu %hu", 1191145510Sdarrenr hostname(res, v, d), proto, hl, plen); 1192145510Sdarrenr } 1193145510Sdarrenr } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { 1194145510Sdarrenr ic = (struct icmp *)((char *)ip + hl); 1195145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1196145510Sdarrenr t += strlen(t); 1197145510Sdarrenr (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 1198145510Sdarrenr hostname(res, v, d), hl, plen, 1199145510Sdarrenr icmpname6(ic->icmp_type, ic->icmp_code)); 1200145510Sdarrenr } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { 1201145510Sdarrenr ic = (struct icmp *)((char *)ip + hl); 1202145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1203145510Sdarrenr t += strlen(t); 1204145510Sdarrenr (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", 1205145510Sdarrenr hostname(res, v, d), hl, plen, 1206145510Sdarrenr icmpname(ic->icmp_type, ic->icmp_code)); 1207145510Sdarrenr if (ic->icmp_type == ICMP_UNREACH || 1208145510Sdarrenr ic->icmp_type == ICMP_SOURCEQUENCH || 1209145510Sdarrenr ic->icmp_type == ICMP_PARAMPROB || 1210145510Sdarrenr ic->icmp_type == ICMP_REDIRECT || 1211145510Sdarrenr ic->icmp_type == ICMP_TIMXCEED) { 1212145510Sdarrenr ipc = &ic->icmp_ip; 1213145510Sdarrenr i = ntohs(ipc->ip_len); 1214145510Sdarrenr /* 1215145510Sdarrenr * XXX - try to guess endian of ip_len in ICMP 1216145510Sdarrenr * returned data. 1217145510Sdarrenr */ 1218145510Sdarrenr if (i > 1500) 1219145510Sdarrenr i = ipc->ip_len; 1220145510Sdarrenr ipoff = ntohs(ipc->ip_off); 1221145510Sdarrenr proto = getproto(ipc->ip_p); 1222145510Sdarrenr 1223145510Sdarrenr if (!(ipoff & IP_OFFMASK) && 1224145510Sdarrenr ((ipc->ip_p == IPPROTO_TCP) || 1225145510Sdarrenr (ipc->ip_p == IPPROTO_UDP))) { 1226145510Sdarrenr tp = (tcphdr_t *)((char *)ipc + hl); 1227145510Sdarrenr t += strlen(t); 1228145510Sdarrenr (void) sprintf(t, " for %s,%s -", 1229145510Sdarrenr HOSTNAME_V4(res, ipc->ip_src), 1230145510Sdarrenr portname(res, proto, 1231145510Sdarrenr (u_int)tp->th_sport)); 1232145510Sdarrenr t += strlen(t); 1233145510Sdarrenr (void) sprintf(t, " %s,%s PR %s len %hu %hu", 1234145510Sdarrenr HOSTNAME_V4(res, ipc->ip_dst), 1235145510Sdarrenr portname(res, proto, 1236145510Sdarrenr (u_int)tp->th_dport), 1237145510Sdarrenr proto, IP_HL(ipc) << 2, i); 1238145510Sdarrenr } else if (!(ipoff & IP_OFFMASK) && 1239145510Sdarrenr (ipc->ip_p == IPPROTO_ICMP)) { 1240145510Sdarrenr icmp = (icmphdr_t *)((char *)ipc + hl); 1241145510Sdarrenr 1242145510Sdarrenr t += strlen(t); 1243145510Sdarrenr (void) sprintf(t, " for %s -", 1244145510Sdarrenr HOSTNAME_V4(res, ipc->ip_src)); 1245145510Sdarrenr t += strlen(t); 1246145510Sdarrenr (void) sprintf(t, 1247145510Sdarrenr " %s PR icmp len %hu %hu icmp %d/%d", 1248145510Sdarrenr HOSTNAME_V4(res, ipc->ip_dst), 1249145510Sdarrenr IP_HL(ipc) << 2, i, 1250145510Sdarrenr icmp->icmp_type, icmp->icmp_code); 1251145510Sdarrenr } else { 1252145510Sdarrenr t += strlen(t); 1253145510Sdarrenr (void) sprintf(t, " for %s -", 1254145510Sdarrenr HOSTNAME_V4(res, ipc->ip_src)); 1255145510Sdarrenr t += strlen(t); 1256145510Sdarrenr (void) sprintf(t, " %s PR %s len %hu (%hu)", 1257145510Sdarrenr HOSTNAME_V4(res, ipc->ip_dst), proto, 1258145510Sdarrenr IP_HL(ipc) << 2, i); 1259145510Sdarrenr t += strlen(t); 1260145510Sdarrenr if (ipoff & IP_OFFMASK) { 1261145510Sdarrenr (void) sprintf(t, 1262145510Sdarrenr "(frag %d:%hu@%hu%s%s)", 1263145510Sdarrenr ntohs(ipc->ip_id), 1264145510Sdarrenr i - (IP_HL(ipc) << 2), 1265145510Sdarrenr (ipoff & IP_OFFMASK) << 3, 1266145510Sdarrenr ipoff & IP_MF ? "+" : "", 1267145510Sdarrenr ipoff & IP_DF ? "-" : ""); 1268145510Sdarrenr } 1269145510Sdarrenr } 1270145510Sdarrenr 1271145510Sdarrenr } 1272145510Sdarrenr } else { 1273145510Sdarrenr (void) sprintf(t, "%s -> ", hostname(res, v, s)); 1274145510Sdarrenr t += strlen(t); 1275145510Sdarrenr (void) sprintf(t, "%s PR %s len %hu (%hu)", 1276145510Sdarrenr hostname(res, v, d), proto, hl, plen); 1277145510Sdarrenr t += strlen(t); 1278145510Sdarrenr if (off & IP_OFFMASK) 1279145510Sdarrenr (void) sprintf(t, " (frag %d:%hu@%hu%s%s)", 1280145510Sdarrenr ntohs(ip->ip_id), 1281145510Sdarrenr plen - hl, (off & IP_OFFMASK) << 3, 1282145510Sdarrenr ipoff & IP_MF ? "+" : "", 1283145510Sdarrenr ipoff & IP_DF ? "-" : ""); 1284145510Sdarrenr } 1285145510Sdarrenr t += strlen(t); 1286145510Sdarrenr 1287145510Sdarrenrprintipflog: 1288145510Sdarrenr if (ipf->fl_flags & FR_KEEPSTATE) { 1289145510Sdarrenr (void) strcpy(t, " K-S"); 1290145510Sdarrenr t += strlen(t); 1291145510Sdarrenr } 1292145510Sdarrenr 1293145510Sdarrenr if (ipf->fl_flags & FR_KEEPFRAG) { 1294145510Sdarrenr (void) strcpy(t, " K-F"); 1295145510Sdarrenr t += strlen(t); 1296145510Sdarrenr } 1297145510Sdarrenr 1298145510Sdarrenr if (ipf->fl_dir == 0) 1299145510Sdarrenr strcpy(t, " IN"); 1300145510Sdarrenr else if (ipf->fl_dir == 1) 1301145510Sdarrenr strcpy(t, " OUT"); 1302145510Sdarrenr t += strlen(t); 1303145510Sdarrenr if (ipf->fl_logtag != 0) { 1304145510Sdarrenr sprintf(t, " log-tag %d", ipf->fl_logtag); 1305145510Sdarrenr t += strlen(t); 1306145510Sdarrenr } 1307145510Sdarrenr if (ipf->fl_nattag.ipt_num[0] != 0) { 1308145510Sdarrenr strcpy(t, " nat-tag "); 1309145510Sdarrenr t += strlen(t); 1310145510Sdarrenr strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 1311145510Sdarrenr t += strlen(t); 1312145510Sdarrenr } 1313145510Sdarrenr if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 1314145510Sdarrenr strcpy(t, " low-ttl"); 1315145510Sdarrenr t += 8; 1316145510Sdarrenr } 1317145510Sdarrenr if ((ipf->fl_lflags & FI_OOW) != 0) { 1318145510Sdarrenr strcpy(t, " OOW"); 1319145510Sdarrenr t += 4; 1320145510Sdarrenr } 1321145510Sdarrenr if ((ipf->fl_lflags & FI_BAD) != 0) { 1322145510Sdarrenr strcpy(t, " bad"); 1323145510Sdarrenr t += 4; 1324145510Sdarrenr } 1325145510Sdarrenr if ((ipf->fl_lflags & FI_NATED) != 0) { 1326145510Sdarrenr strcpy(t, " NAT"); 1327145510Sdarrenr t += 4; 1328145510Sdarrenr } 1329145510Sdarrenr if ((ipf->fl_lflags & FI_BADNAT) != 0) { 1330145510Sdarrenr strcpy(t, " bad-NAT"); 1331145510Sdarrenr t += 8; 1332145510Sdarrenr } 1333145510Sdarrenr if ((ipf->fl_lflags & FI_BADSRC) != 0) { 1334145510Sdarrenr strcpy(t, " bad-src"); 1335145510Sdarrenr t += 8; 1336145510Sdarrenr } 1337145510Sdarrenr if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 1338145510Sdarrenr strcpy(t, " multicast"); 1339145510Sdarrenr t += 10; 1340145510Sdarrenr } 1341145510Sdarrenr if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 1342145510Sdarrenr strcpy(t, " broadcast"); 1343145510Sdarrenr t += 10; 1344145510Sdarrenr } 1345145510Sdarrenr if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 1346145510Sdarrenr FI_MBCAST) { 1347145510Sdarrenr strcpy(t, " mbcast"); 1348145510Sdarrenr t += 7; 1349145510Sdarrenr } 1350145510Sdarrenr *t++ = '\n'; 1351145510Sdarrenr *t++ = '\0'; 1352145510Sdarrenr defaction = 0; 1353145510Sdarrenr if (conf_file != NULL) 1354145510Sdarrenr defaction = check_action(buf, line, opts, lvl); 1355145510Sdarrenr if (defaction == 0) { 1356145510Sdarrenr if (opts & OPT_SYSLOG) 1357145510Sdarrenr syslog(lvl, "%s", line); 1358161357Sguido else if (log != NULL) 1359145510Sdarrenr (void) fprintf(log, "%s", line); 1360161357Sguido 1361145510Sdarrenr if (opts & OPT_HEXHDR) 1362145510Sdarrenr dumphex(log, opts, buf, 1363145510Sdarrenr sizeof(iplog_t) + sizeof(*ipf)); 1364145510Sdarrenr if (opts & OPT_HEXBODY) 1365145510Sdarrenr dumphex(log, opts, (char *)ip, 1366145510Sdarrenr ipf->fl_plen + ipf->fl_hlen); 1367145510Sdarrenr else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) 1368145510Sdarrenr dumphex(log, opts, (char *)ip + ipf->fl_hlen, 1369145510Sdarrenr ipf->fl_plen); 1370145510Sdarrenr } 1371145510Sdarrenr} 1372145510Sdarrenr 1373145510Sdarrenr 1374145510Sdarrenrstatic void usage(prog) 1375145510Sdarrenrchar *prog; 1376145510Sdarrenr{ 1377145510Sdarrenr fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog); 1378145510Sdarrenr exit(1); 1379145510Sdarrenr} 1380145510Sdarrenr 1381145510Sdarrenr 1382145510Sdarrenrstatic void write_pid(file) 1383145510Sdarrenrchar *file; 1384145510Sdarrenr{ 1385145510Sdarrenr FILE *fp = NULL; 1386145510Sdarrenr int fd; 1387145510Sdarrenr 1388145510Sdarrenr if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 1389145510Sdarrenr fp = fdopen(fd, "w"); 1390145510Sdarrenr if (fp == NULL) { 1391145510Sdarrenr close(fd); 1392145510Sdarrenr fprintf(stderr, 1393145510Sdarrenr "unable to open/create pid file: %s\n", file); 1394145510Sdarrenr return; 1395145510Sdarrenr } 1396145510Sdarrenr fprintf(fp, "%d", getpid()); 1397145510Sdarrenr fclose(fp); 1398145510Sdarrenr } 1399145510Sdarrenr} 1400145510Sdarrenr 1401145510Sdarrenr 1402145510Sdarrenrstatic void flushlogs(file, log) 1403145510Sdarrenrchar *file; 1404145510SdarrenrFILE *log; 1405145510Sdarrenr{ 1406145510Sdarrenr int fd, flushed = 0; 1407145510Sdarrenr 1408145510Sdarrenr if ((fd = open(file, O_RDWR)) == -1) { 1409145510Sdarrenr (void) fprintf(stderr, "%s: open: %s\n", 1410145510Sdarrenr file, STRERROR(errno)); 1411145510Sdarrenr exit(1); 1412145510Sdarrenr } 1413145510Sdarrenr 1414145510Sdarrenr if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 1415145510Sdarrenr printf("%d bytes flushed from log buffer\n", 1416145510Sdarrenr flushed); 1417145510Sdarrenr fflush(stdout); 1418145510Sdarrenr } else 1419145510Sdarrenr perror("SIOCIPFFB"); 1420145510Sdarrenr (void) close(fd); 1421145510Sdarrenr 1422145510Sdarrenr if (flushed) { 1423161357Sguido if (opts & OPT_SYSLOG) { 1424145510Sdarrenr syslog(LOG_INFO, "%d bytes flushed from log\n", 1425145510Sdarrenr flushed); 1426161357Sguido } else if ((log != stdout) && (log != NULL)) { 1427145510Sdarrenr fprintf(log, "%d bytes flushed from log\n", flushed); 1428161357Sguido } 1429145510Sdarrenr } 1430145510Sdarrenr} 1431145510Sdarrenr 1432145510Sdarrenr 1433145510Sdarrenrstatic void logopts(turnon, options) 1434145510Sdarrenrint turnon; 1435145510Sdarrenrchar *options; 1436145510Sdarrenr{ 1437145510Sdarrenr int flags = 0; 1438145510Sdarrenr char *s; 1439145510Sdarrenr 1440145510Sdarrenr for (s = options; *s; s++) 1441145510Sdarrenr { 1442145510Sdarrenr switch (*s) 1443145510Sdarrenr { 1444145510Sdarrenr case 'N' : 1445145510Sdarrenr flags |= OPT_NAT; 1446145510Sdarrenr break; 1447145510Sdarrenr case 'S' : 1448145510Sdarrenr flags |= OPT_STATE; 1449145510Sdarrenr break; 1450145510Sdarrenr case 'I' : 1451145510Sdarrenr flags |= OPT_FILTER; 1452145510Sdarrenr break; 1453145510Sdarrenr default : 1454145510Sdarrenr fprintf(stderr, "Unknown log option %c\n", *s); 1455145510Sdarrenr exit(1); 1456145510Sdarrenr } 1457145510Sdarrenr } 1458145510Sdarrenr 1459145510Sdarrenr if (turnon) 1460145510Sdarrenr opts |= flags; 1461145510Sdarrenr else 1462145510Sdarrenr opts &= ~(flags); 1463145510Sdarrenr} 1464145510Sdarrenr 1465145510Sdarrenr 1466145510Sdarrenrint main(argc, argv) 1467145510Sdarrenrint argc; 1468145510Sdarrenrchar *argv[]; 1469145510Sdarrenr{ 1470145510Sdarrenr struct stat sb; 1471145510Sdarrenr FILE *log = stdout; 1472145510Sdarrenr FILE *fp; 1473145510Sdarrenr int fd[3], doread, n, i; 1474145510Sdarrenr int tr, nr, regular[3], c; 1475145510Sdarrenr int fdt[3], devices = 0, make_daemon = 0; 1476145510Sdarrenr char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; 1477145510Sdarrenr extern int optind; 1478145510Sdarrenr extern char *optarg; 1479145510Sdarrenr 1480145510Sdarrenr fd[0] = fd[1] = fd[2] = -1; 1481145510Sdarrenr fdt[0] = fdt[1] = fdt[2] = -1; 1482145510Sdarrenr iplfile[0] = IPL_NAME; 1483145510Sdarrenr iplfile[1] = IPNAT_NAME; 1484145510Sdarrenr iplfile[2] = IPSTATE_NAME; 1485145510Sdarrenr 1486161357Sguido while ((c = getopt(argc, argv, 1487161357Sguido "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) 1488145510Sdarrenr switch (c) 1489145510Sdarrenr { 1490145510Sdarrenr case 'a' : 1491145510Sdarrenr opts |= OPT_LOGALL; 1492145510Sdarrenr fdt[0] = IPL_LOGIPF; 1493145510Sdarrenr fdt[1] = IPL_LOGNAT; 1494145510Sdarrenr fdt[2] = IPL_LOGSTATE; 1495145510Sdarrenr break; 1496145510Sdarrenr case 'b' : 1497145510Sdarrenr opts |= OPT_LOGBODY; 1498145510Sdarrenr break; 1499145510Sdarrenr case 'B' : 1500145510Sdarrenr binarylogfile = optarg; 1501145510Sdarrenr binarylog = fopen(optarg, "a"); 1502145510Sdarrenr break; 1503145510Sdarrenr case 'C' : 1504145510Sdarrenr conf_file = optarg; 1505145510Sdarrenr break; 1506145510Sdarrenr case 'D' : 1507145510Sdarrenr make_daemon = 1; 1508145510Sdarrenr break; 1509145510Sdarrenr case 'f' : case 'I' : 1510145510Sdarrenr opts |= OPT_FILTER; 1511145510Sdarrenr fdt[0] = IPL_LOGIPF; 1512145510Sdarrenr iplfile[0] = optarg; 1513145510Sdarrenr break; 1514145510Sdarrenr case 'F' : 1515145510Sdarrenr flushlogs(iplfile[0], log); 1516145510Sdarrenr flushlogs(iplfile[1], log); 1517145510Sdarrenr flushlogs(iplfile[2], log); 1518145510Sdarrenr break; 1519161357Sguido case 'L' : 1520161357Sguido logfac = fac_findname(optarg); 1521161357Sguido if (logfac == -1) { 1522161357Sguido fprintf(stderr, 1523161357Sguido "Unknown syslog facility '%s'\n", 1524161357Sguido optarg); 1525161357Sguido exit(1); 1526161357Sguido } 1527161357Sguido break; 1528145510Sdarrenr case 'n' : 1529145510Sdarrenr opts |= OPT_RESOLVE; 1530145510Sdarrenr break; 1531145510Sdarrenr case 'N' : 1532145510Sdarrenr opts |= OPT_NAT; 1533145510Sdarrenr fdt[1] = IPL_LOGNAT; 1534145510Sdarrenr iplfile[1] = optarg; 1535145510Sdarrenr break; 1536145510Sdarrenr case 'o' : case 'O' : 1537145510Sdarrenr logopts(c == 'o', optarg); 1538145510Sdarrenr fdt[0] = fdt[1] = fdt[2] = -1; 1539145510Sdarrenr if (opts & OPT_FILTER) 1540145510Sdarrenr fdt[0] = IPL_LOGIPF; 1541145510Sdarrenr if (opts & OPT_NAT) 1542145510Sdarrenr fdt[1] = IPL_LOGNAT; 1543145510Sdarrenr if (opts & OPT_STATE) 1544145510Sdarrenr fdt[2] = IPL_LOGSTATE; 1545145510Sdarrenr break; 1546145510Sdarrenr case 'p' : 1547145510Sdarrenr opts |= OPT_PORTNUM; 1548145510Sdarrenr break; 1549145510Sdarrenr case 'P' : 1550145510Sdarrenr pidfile = optarg; 1551145510Sdarrenr break; 1552145510Sdarrenr case 's' : 1553145510Sdarrenr s = strrchr(argv[0], '/'); 1554145510Sdarrenr if (s == NULL) 1555145510Sdarrenr s = argv[0]; 1556145510Sdarrenr else 1557145510Sdarrenr s++; 1558161357Sguido openlog(s, LOG_NDELAY|LOG_PID, logfac); 1559145510Sdarrenr s = NULL; 1560145510Sdarrenr opts |= OPT_SYSLOG; 1561145510Sdarrenr log = NULL; 1562145510Sdarrenr break; 1563145510Sdarrenr case 'S' : 1564145510Sdarrenr opts |= OPT_STATE; 1565145510Sdarrenr fdt[2] = IPL_LOGSTATE; 1566145510Sdarrenr iplfile[2] = optarg; 1567145510Sdarrenr break; 1568145510Sdarrenr case 't' : 1569145510Sdarrenr opts |= OPT_TAIL; 1570145510Sdarrenr break; 1571145510Sdarrenr case 'v' : 1572145510Sdarrenr opts |= OPT_VERBOSE; 1573145510Sdarrenr break; 1574145510Sdarrenr case 'x' : 1575145510Sdarrenr opts |= OPT_HEXBODY; 1576145510Sdarrenr break; 1577145510Sdarrenr case 'X' : 1578145510Sdarrenr opts |= OPT_HEXHDR; 1579145510Sdarrenr break; 1580145510Sdarrenr default : 1581145510Sdarrenr case 'h' : 1582145510Sdarrenr case '?' : 1583145510Sdarrenr usage(argv[0]); 1584145510Sdarrenr } 1585145510Sdarrenr 1586145510Sdarrenr init_tabs(); 1587145510Sdarrenr if (conf_file) 1588145510Sdarrenr if (load_config(conf_file) == -1) 1589145510Sdarrenr exit(1); 1590145510Sdarrenr 1591145510Sdarrenr /* 1592145510Sdarrenr * Default action is to only open the filter log file. 1593145510Sdarrenr */ 1594145510Sdarrenr if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) 1595145510Sdarrenr fdt[0] = IPL_LOGIPF; 1596145510Sdarrenr 1597145510Sdarrenr for (i = 0; i < 3; i++) { 1598145510Sdarrenr if (fdt[i] == -1) 1599145510Sdarrenr continue; 1600145510Sdarrenr if (!strcmp(iplfile[i], "-")) 1601145510Sdarrenr fd[i] = 0; 1602145510Sdarrenr else { 1603145510Sdarrenr if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { 1604145510Sdarrenr (void) fprintf(stderr, 1605145510Sdarrenr "%s: open: %s\n", iplfile[i], 1606145510Sdarrenr STRERROR(errno)); 1607145510Sdarrenr exit(1); 1608145510Sdarrenr /* NOTREACHED */ 1609145510Sdarrenr } 1610145510Sdarrenr if (fstat(fd[i], &sb) == -1) { 1611145510Sdarrenr (void) fprintf(stderr, "%d: fstat: %s\n", 1612145510Sdarrenr fd[i], STRERROR(errno)); 1613145510Sdarrenr exit(1); 1614145510Sdarrenr /* NOTREACHED */ 1615145510Sdarrenr } 1616145510Sdarrenr if (!(regular[i] = !S_ISCHR(sb.st_mode))) 1617145510Sdarrenr devices++; 1618145510Sdarrenr } 1619145510Sdarrenr } 1620145510Sdarrenr 1621145510Sdarrenr if (!(opts & OPT_SYSLOG)) { 1622145510Sdarrenr logfile = argv[optind]; 1623145510Sdarrenr log = logfile ? fopen(logfile, "a") : stdout; 1624145510Sdarrenr if (log == NULL) { 1625145510Sdarrenr (void) fprintf(stderr, "%s: fopen: %s\n", 1626145510Sdarrenr argv[optind], STRERROR(errno)); 1627145510Sdarrenr exit(1); 1628145510Sdarrenr /* NOTREACHED */ 1629145510Sdarrenr } 1630145510Sdarrenr setvbuf(log, NULL, _IONBF, 0); 1631145510Sdarrenr } else 1632145510Sdarrenr log = NULL; 1633145510Sdarrenr 1634145510Sdarrenr if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { 1635145510Sdarrenr#if BSD >= 199306 1636145510Sdarrenr daemon(0, !(opts & OPT_SYSLOG)); 1637145510Sdarrenr#else 1638145510Sdarrenr int pid; 1639145510Sdarrenr if ((pid = fork()) > 0) 1640145510Sdarrenr exit(0); 1641145510Sdarrenr if (pid < 0) { 1642145510Sdarrenr (void) fprintf(stderr, "%s: fork() failed: %s\n", 1643145510Sdarrenr argv[0], STRERROR(errno)); 1644145510Sdarrenr exit(1); 1645145510Sdarrenr /* NOTREACHED */ 1646145510Sdarrenr } 1647145510Sdarrenr setsid(); 1648145510Sdarrenr if ((opts & OPT_SYSLOG)) 1649145510Sdarrenr close(2); 1650145510Sdarrenr#endif /* !BSD */ 1651145510Sdarrenr close(0); 1652145510Sdarrenr close(1); 1653161357Sguido write_pid(pidfile); 1654145510Sdarrenr } 1655145510Sdarrenr 1656145510Sdarrenr signal(SIGHUP, handlehup); 1657145510Sdarrenr 1658145510Sdarrenr for (doread = 1; doread; ) { 1659145510Sdarrenr nr = 0; 1660145510Sdarrenr 1661145510Sdarrenr for (i = 0; i < 3; i++) { 1662145510Sdarrenr tr = 0; 1663145510Sdarrenr if (fdt[i] == -1) 1664145510Sdarrenr continue; 1665145510Sdarrenr if (!regular[i]) { 1666145510Sdarrenr if (ioctl(fd[i], FIONREAD, &tr) == -1) { 1667145510Sdarrenr if (opts & OPT_SYSLOG) 1668145510Sdarrenr syslog(LOG_CRIT, 1669145510Sdarrenr "ioctl(FIONREAD): %m"); 1670145510Sdarrenr else 1671145510Sdarrenr perror("ioctl(FIONREAD)"); 1672145510Sdarrenr exit(1); 1673145510Sdarrenr /* NOTREACHED */ 1674145510Sdarrenr } 1675145510Sdarrenr } else { 1676145510Sdarrenr tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); 1677145510Sdarrenr if (!tr && !(opts & OPT_TAIL)) 1678145510Sdarrenr doread = 0; 1679145510Sdarrenr } 1680145510Sdarrenr if (!tr) 1681145510Sdarrenr continue; 1682145510Sdarrenr nr += tr; 1683170268Sdarrenr n = 0; 1684145510Sdarrenr 1685145510Sdarrenr tr = read_log(fd[i], &n, buf, sizeof(buf)); 1686145510Sdarrenr if (donehup) { 1687145510Sdarrenr if (logfile && (fp = fopen(logfile, "a"))) { 1688145510Sdarrenr fclose(log); 1689145510Sdarrenr log = fp; 1690145510Sdarrenr } 1691161357Sguido if (binarylogfile && 1692161357Sguido (fp = fopen(binarylogfile, "a"))) { 1693145510Sdarrenr fclose(binarylog); 1694145510Sdarrenr binarylog = fp; 1695145510Sdarrenr } 1696145510Sdarrenr init_tabs(); 1697145510Sdarrenr if (conf_file != NULL) 1698145510Sdarrenr load_config(conf_file); 1699145510Sdarrenr donehup = 0; 1700145510Sdarrenr } 1701145510Sdarrenr 1702145510Sdarrenr switch (tr) 1703145510Sdarrenr { 1704145510Sdarrenr case -1 : 1705145510Sdarrenr if (opts & OPT_SYSLOG) 1706145510Sdarrenr syslog(LOG_CRIT, "read: %m\n"); 1707145510Sdarrenr else 1708145510Sdarrenr perror("read"); 1709145510Sdarrenr doread = 0; 1710145510Sdarrenr break; 1711145510Sdarrenr case 1 : 1712145510Sdarrenr if (opts & OPT_SYSLOG) 1713145510Sdarrenr syslog(LOG_CRIT, "aborting logging\n"); 1714161357Sguido else if (log != NULL) 1715145510Sdarrenr fprintf(log, "aborting logging\n"); 1716145510Sdarrenr doread = 0; 1717145510Sdarrenr break; 1718145510Sdarrenr case 2 : 1719145510Sdarrenr break; 1720145510Sdarrenr case 0 : 1721145510Sdarrenr if (n > 0) { 1722145510Sdarrenr print_log(fdt[i], log, buf, n); 1723145510Sdarrenr if (!(opts & OPT_SYSLOG)) 1724145510Sdarrenr fflush(log); 1725145510Sdarrenr } 1726145510Sdarrenr break; 1727145510Sdarrenr } 1728145510Sdarrenr } 1729145510Sdarrenr if (!nr && ((opts & OPT_TAIL) || devices)) 1730145510Sdarrenr sleep(1); 1731145510Sdarrenr } 1732145510Sdarrenr return(0); 1733145510Sdarrenr /* NOTREACHED */ 1734145510Sdarrenr} 1735