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