10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * Copyright (C) 1993-2001, 2003 by Darren Reed. 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing. 50Sstevel@tonic-gate * 60Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 70Sstevel@tonic-gate * Use is subject to license terms. 80Sstevel@tonic-gate */ 90Sstevel@tonic-gate 100Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 110Sstevel@tonic-gate 120Sstevel@tonic-gate #ifndef SOLARIS 130Sstevel@tonic-gate #define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun) 140Sstevel@tonic-gate #endif 150Sstevel@tonic-gate 160Sstevel@tonic-gate #include <sys/types.h> 170Sstevel@tonic-gate #include <sys/stat.h> 180Sstevel@tonic-gate #include <sys/param.h> 190Sstevel@tonic-gate #include <sys/file.h> 200Sstevel@tonic-gate #include <sys/time.h> 210Sstevel@tonic-gate #define _KERNEL 220Sstevel@tonic-gate #include <sys/uio.h> 230Sstevel@tonic-gate #undef _KERNEL 240Sstevel@tonic-gate #include <sys/socket.h> 250Sstevel@tonic-gate #include <sys/ioctl.h> 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <stdio.h> 280Sstevel@tonic-gate #include <unistd.h> 290Sstevel@tonic-gate #include <string.h> 300Sstevel@tonic-gate #include <fcntl.h> 310Sstevel@tonic-gate #include <errno.h> 320Sstevel@tonic-gate #if !defined(__SVR4) && !defined(__svr4__) 330Sstevel@tonic-gate # if (__FreeBSD_version >= 300000) 340Sstevel@tonic-gate # include <sys/dirent.h> 350Sstevel@tonic-gate # else 360Sstevel@tonic-gate # include <sys/dir.h> 370Sstevel@tonic-gate # endif 380Sstevel@tonic-gate #else 390Sstevel@tonic-gate # include <sys/filio.h> 400Sstevel@tonic-gate # include <sys/byteorder.h> 410Sstevel@tonic-gate #endif 420Sstevel@tonic-gate #if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__)) 430Sstevel@tonic-gate # include <strings.h> 440Sstevel@tonic-gate #endif 450Sstevel@tonic-gate #include <signal.h> 460Sstevel@tonic-gate #include <stdlib.h> 470Sstevel@tonic-gate #include <stddef.h> 480Sstevel@tonic-gate #include <netinet/in.h> 490Sstevel@tonic-gate #include <netinet/in_systm.h> 500Sstevel@tonic-gate #include <net/if.h> 510Sstevel@tonic-gate #include <netinet/ip.h> 520Sstevel@tonic-gate #if !defined(__hpux) 530Sstevel@tonic-gate # include <netinet/tcp_fsm.h> 540Sstevel@tonic-gate #endif 550Sstevel@tonic-gate #include <netdb.h> 560Sstevel@tonic-gate #include <arpa/inet.h> 570Sstevel@tonic-gate #include <arpa/nameser.h> 580Sstevel@tonic-gate #ifdef __hpux 590Sstevel@tonic-gate # undef NOERROR 600Sstevel@tonic-gate #endif 610Sstevel@tonic-gate #include <resolv.h> 620Sstevel@tonic-gate 630Sstevel@tonic-gate #include <sys/protosw.h> 640Sstevel@tonic-gate #include <netinet/ip_var.h> 650Sstevel@tonic-gate 660Sstevel@tonic-gate #include <netinet/tcp.h> 670Sstevel@tonic-gate #include <netinet/ip_icmp.h> 680Sstevel@tonic-gate 690Sstevel@tonic-gate #include <ctype.h> 700Sstevel@tonic-gate #include <syslog.h> 710Sstevel@tonic-gate 720Sstevel@tonic-gate #include <netinet/tcpip.h> 730Sstevel@tonic-gate 740Sstevel@tonic-gate #if SOLARIS2 >= 10 750Sstevel@tonic-gate #include "ip_compat.h" 760Sstevel@tonic-gate #include "ip_fil.h" 770Sstevel@tonic-gate #include "ip_nat.h" 780Sstevel@tonic-gate #include "ip_state.h" 790Sstevel@tonic-gate #include "ip_proxy.h" 800Sstevel@tonic-gate #else 810Sstevel@tonic-gate #include "netinet/ip_compat.h" 820Sstevel@tonic-gate #include "netinet/ip_fil.h" 830Sstevel@tonic-gate #include "netinet/ip_nat.h" 840Sstevel@tonic-gate #include "netinet/ip_state.h" 850Sstevel@tonic-gate #include "netinet/ip_proxy.h" 860Sstevel@tonic-gate #endif 870Sstevel@tonic-gate #include "ipmon.h" 880Sstevel@tonic-gate 890Sstevel@tonic-gate #if !defined(lint) 900Sstevel@tonic-gate static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; 910Sstevel@tonic-gate static const char rcsid[] = "@(#)$Id: ipmon.c,v 1.22 2003/06/14 02:56:57 darrenr Exp $"; 920Sstevel@tonic-gate #endif 930Sstevel@tonic-gate 940Sstevel@tonic-gate 950Sstevel@tonic-gate #if defined(sun) && !defined(SOLARIS2) 960Sstevel@tonic-gate #define STRERROR(x) sys_errlist[x] 970Sstevel@tonic-gate extern char *sys_errlist[]; 980Sstevel@tonic-gate #else 990Sstevel@tonic-gate #define STRERROR(x) strerror(x) 1000Sstevel@tonic-gate #endif 1010Sstevel@tonic-gate 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate struct flags { 1040Sstevel@tonic-gate int value; 1050Sstevel@tonic-gate char flag; 1060Sstevel@tonic-gate }; 1070Sstevel@tonic-gate 1080Sstevel@tonic-gate 1090Sstevel@tonic-gate typedef struct icmp_subtype { 1100Sstevel@tonic-gate int ist_val; 1110Sstevel@tonic-gate char *ist_name; 1120Sstevel@tonic-gate } icmp_subtype_t; 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate typedef struct icmp_type { 1150Sstevel@tonic-gate int it_val; 1160Sstevel@tonic-gate struct icmp_subtype *it_subtable; 1170Sstevel@tonic-gate size_t it_stsize; 1180Sstevel@tonic-gate char *it_name; 1190Sstevel@tonic-gate } icmp_type_t; 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate struct flags tcpfl[] = { 1260Sstevel@tonic-gate { TH_ACK, 'A' }, 1270Sstevel@tonic-gate { TH_RST, 'R' }, 1280Sstevel@tonic-gate { TH_SYN, 'S' }, 1290Sstevel@tonic-gate { TH_FIN, 'F' }, 1300Sstevel@tonic-gate { TH_URG, 'U' }, 1310Sstevel@tonic-gate { TH_PUSH,'P' }, 1320Sstevel@tonic-gate { TH_ECN, 'E' }, 1330Sstevel@tonic-gate { TH_CWR, 'C' }, 1340Sstevel@tonic-gate { 0, '\0' } 1350Sstevel@tonic-gate }; 1360Sstevel@tonic-gate 1370Sstevel@tonic-gate #ifdef MENTAT 1380Sstevel@tonic-gate static char *pidfile = "/etc/ipf/ipmon.pid"; 1390Sstevel@tonic-gate #else 1400Sstevel@tonic-gate # if BSD >= 199306 1410Sstevel@tonic-gate static char *pidfile = "/var/run/ipmon.pid"; 1420Sstevel@tonic-gate # else 1430Sstevel@tonic-gate static char *pidfile = "/etc/ipmon.pid"; 1440Sstevel@tonic-gate # endif 1450Sstevel@tonic-gate #endif 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate static char line[2048]; 1480Sstevel@tonic-gate static int opts = 0; 1490Sstevel@tonic-gate static FILE *newlog = NULL; 1500Sstevel@tonic-gate static char *logfile = NULL; 1510Sstevel@tonic-gate static FILE *binarylog = NULL; 1520Sstevel@tonic-gate static FILE *newbinarylog = NULL; 1530Sstevel@tonic-gate static char *binarylogfile = NULL; 1540Sstevel@tonic-gate static int donehup = 0; 1550Sstevel@tonic-gate static void usage __P((char *)); 1560Sstevel@tonic-gate static void handlehup __P((int)); 1570Sstevel@tonic-gate static void flushlogs __P((char *, FILE *)); 1580Sstevel@tonic-gate static void print_log __P((int, FILE *, char *, int)); 1590Sstevel@tonic-gate static void print_ipflog __P((FILE *, char *, int)); 1600Sstevel@tonic-gate static void print_natlog __P((FILE *, char *, int)); 1610Sstevel@tonic-gate static void print_statelog __P((FILE *, char *, int)); 1620Sstevel@tonic-gate static int read_log __P((int, int *, char *, int)); 1630Sstevel@tonic-gate static void write_pid __P((char *)); 1640Sstevel@tonic-gate static char *icmpname __P((u_int, u_int)); 1650Sstevel@tonic-gate static char *icmpname6 __P((u_int, u_int)); 1660Sstevel@tonic-gate static icmp_type_t *find_icmptype __P((int, icmp_type_t *, size_t)); 1670Sstevel@tonic-gate static icmp_subtype_t *find_icmpsubtype __P((int, icmp_subtype_t *, size_t)); 1680Sstevel@tonic-gate #ifdef __hpux 1690Sstevel@tonic-gate static struct tm *get_tm __P((u_32_t)); 1700Sstevel@tonic-gate #else 1710Sstevel@tonic-gate static struct tm *get_tm __P((time_t)); 1720Sstevel@tonic-gate #endif 1730Sstevel@tonic-gate 1740Sstevel@tonic-gate char *hostname __P((int, int, u_32_t *)); 1750Sstevel@tonic-gate char *portname __P((int, char *, u_int)); 1760Sstevel@tonic-gate int main __P((int, char *[])); 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate static void logopts __P((int, char *)); 1790Sstevel@tonic-gate static void init_tabs __P((void)); 1800Sstevel@tonic-gate static char *getproto __P((u_int)); 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate static char **protocols = NULL; 1830Sstevel@tonic-gate static char **udp_ports = NULL; 1840Sstevel@tonic-gate static char **tcp_ports = NULL; 1850Sstevel@tonic-gate static char *conf_file = NULL; 1860Sstevel@tonic-gate 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate #define OPT_SYSLOG 0x001 1890Sstevel@tonic-gate #define OPT_RESOLVE 0x002 1900Sstevel@tonic-gate #define OPT_HEXBODY 0x004 1910Sstevel@tonic-gate #define OPT_VERBOSE 0x008 1920Sstevel@tonic-gate #define OPT_HEXHDR 0x010 1930Sstevel@tonic-gate #define OPT_TAIL 0x020 1940Sstevel@tonic-gate #define OPT_NAT 0x080 1950Sstevel@tonic-gate #define OPT_STATE 0x100 1960Sstevel@tonic-gate #define OPT_FILTER 0x200 1970Sstevel@tonic-gate #define OPT_PORTNUM 0x400 1980Sstevel@tonic-gate #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER) 1990Sstevel@tonic-gate #define OPT_LOGBODY 0x800 2000Sstevel@tonic-gate 2010Sstevel@tonic-gate #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b)) 2020Sstevel@tonic-gate 2030Sstevel@tonic-gate #ifndef LOGFAC 2040Sstevel@tonic-gate #define LOGFAC LOG_LOCAL0 2050Sstevel@tonic-gate #endif 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate static icmp_subtype_t icmpunreachnames[] = { 2090Sstevel@tonic-gate { ICMP_UNREACH_NET, "net" }, 2100Sstevel@tonic-gate { ICMP_UNREACH_HOST, "host" }, 2110Sstevel@tonic-gate { ICMP_UNREACH_PROTOCOL, "protocol" }, 2120Sstevel@tonic-gate { ICMP_UNREACH_PORT, "port" }, 2130Sstevel@tonic-gate { ICMP_UNREACH_NEEDFRAG, "needfrag" }, 2140Sstevel@tonic-gate { ICMP_UNREACH_SRCFAIL, "srcfail" }, 2150Sstevel@tonic-gate { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, 2160Sstevel@tonic-gate { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, 2170Sstevel@tonic-gate { ICMP_UNREACH_NET, "isolated" }, 2180Sstevel@tonic-gate { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, 2190Sstevel@tonic-gate { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, 2200Sstevel@tonic-gate { ICMP_UNREACH_TOSNET, "tosnet" }, 2210Sstevel@tonic-gate { ICMP_UNREACH_TOSHOST, "toshost" }, 2220Sstevel@tonic-gate { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, 2230Sstevel@tonic-gate { -2, NULL } 2240Sstevel@tonic-gate }; 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate static icmp_subtype_t redirectnames[] = { 2270Sstevel@tonic-gate { ICMP_REDIRECT_NET, "net" }, 2280Sstevel@tonic-gate { ICMP_REDIRECT_HOST, "host" }, 2290Sstevel@tonic-gate { ICMP_REDIRECT_TOSNET, "tosnet" }, 2300Sstevel@tonic-gate { ICMP_REDIRECT_TOSHOST, "toshost" }, 2310Sstevel@tonic-gate { -2, NULL } 2320Sstevel@tonic-gate }; 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate static icmp_subtype_t timxceednames[] = { 2350Sstevel@tonic-gate { ICMP_TIMXCEED_INTRANS, "transit" }, 2360Sstevel@tonic-gate { ICMP_TIMXCEED_REASS, "reassem" }, 2370Sstevel@tonic-gate { -2, NULL } 2380Sstevel@tonic-gate }; 2390Sstevel@tonic-gate 2400Sstevel@tonic-gate static icmp_subtype_t paramnames[] = { 2410Sstevel@tonic-gate { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, 2420Sstevel@tonic-gate { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, 2430Sstevel@tonic-gate { ICMP_PARAMPROB_LENGTH, "length" }, 2440Sstevel@tonic-gate { -2, NULL } 2450Sstevel@tonic-gate }; 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate static icmp_type_t icmptypes[] = { 2480Sstevel@tonic-gate { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, 2490Sstevel@tonic-gate { -1, NULL, 0, NULL }, 2500Sstevel@tonic-gate { -1, NULL, 0, NULL }, 2510Sstevel@tonic-gate { ICMP_UNREACH, icmpunreachnames, 2520Sstevel@tonic-gate IST_SZ(icmpunreachnames),"unreach" }, 2530Sstevel@tonic-gate { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, 2540Sstevel@tonic-gate { ICMP_REDIRECT, redirectnames, 2550Sstevel@tonic-gate IST_SZ(redirectnames), "redirect" }, 2560Sstevel@tonic-gate { -1, NULL, 0, NULL }, 2570Sstevel@tonic-gate { -1, NULL, 0, NULL }, 2580Sstevel@tonic-gate { ICMP_ECHO, NULL, 0, "echo" }, 2590Sstevel@tonic-gate { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, 2600Sstevel@tonic-gate { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, 2610Sstevel@tonic-gate { ICMP_TIMXCEED, timxceednames, 2620Sstevel@tonic-gate IST_SZ(timxceednames), "timxceed" }, 2630Sstevel@tonic-gate { ICMP_PARAMPROB, paramnames, 2640Sstevel@tonic-gate IST_SZ(paramnames), "paramprob" }, 2650Sstevel@tonic-gate { ICMP_TSTAMP, NULL, 0, "timestamp" }, 2660Sstevel@tonic-gate { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, 2670Sstevel@tonic-gate { ICMP_IREQ, NULL, 0, "inforeq" }, 2680Sstevel@tonic-gate { ICMP_IREQREPLY, NULL, 0, "inforeply" }, 2690Sstevel@tonic-gate { ICMP_MASKREQ, NULL, 0, "maskreq" }, 2700Sstevel@tonic-gate { ICMP_MASKREPLY, NULL, 0, "maskreply" }, 2710Sstevel@tonic-gate { -2, NULL, 0, NULL } 2720Sstevel@tonic-gate }; 2730Sstevel@tonic-gate 2740Sstevel@tonic-gate static icmp_subtype_t icmpredirect6[] = { 2750Sstevel@tonic-gate { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, 2760Sstevel@tonic-gate { ICMP6_DST_UNREACH_ADMIN, "admin" }, 2770Sstevel@tonic-gate { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, 2780Sstevel@tonic-gate { ICMP6_DST_UNREACH_ADDR, "address" }, 2790Sstevel@tonic-gate { ICMP6_DST_UNREACH_NOPORT, "noport" }, 2800Sstevel@tonic-gate { -2, NULL } 2810Sstevel@tonic-gate }; 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate static icmp_subtype_t icmptimexceed6[] = { 2840Sstevel@tonic-gate { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, 2850Sstevel@tonic-gate { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, 2860Sstevel@tonic-gate { -2, NULL } 2870Sstevel@tonic-gate }; 2880Sstevel@tonic-gate 2890Sstevel@tonic-gate static icmp_subtype_t icmpparamprob6[] = { 2900Sstevel@tonic-gate { ICMP6_PARAMPROB_HEADER, "header" }, 2910Sstevel@tonic-gate { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, 2920Sstevel@tonic-gate { ICMP6_PARAMPROB_OPTION, "option" }, 2930Sstevel@tonic-gate { -2, NULL } 2940Sstevel@tonic-gate }; 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate static icmp_subtype_t icmpquerysubject6[] = { 2970Sstevel@tonic-gate { ICMP6_NI_SUBJ_IPV6, "ipv6" }, 2980Sstevel@tonic-gate { ICMP6_NI_SUBJ_FQDN, "fqdn" }, 2990Sstevel@tonic-gate { ICMP6_NI_SUBJ_IPV4, "ipv4" }, 3000Sstevel@tonic-gate { -2, NULL }, 3010Sstevel@tonic-gate }; 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate static icmp_subtype_t icmpnodeinfo6[] = { 3040Sstevel@tonic-gate { ICMP6_NI_SUCCESS, "success" }, 3050Sstevel@tonic-gate { ICMP6_NI_REFUSED, "refused" }, 3060Sstevel@tonic-gate { ICMP6_NI_UNKNOWN, "unknown" }, 3070Sstevel@tonic-gate { -2, NULL } 3080Sstevel@tonic-gate }; 3090Sstevel@tonic-gate 3100Sstevel@tonic-gate static icmp_subtype_t icmprenumber6[] = { 3110Sstevel@tonic-gate { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, 3120Sstevel@tonic-gate { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, 3130Sstevel@tonic-gate { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, 3140Sstevel@tonic-gate { -2, NULL } 3150Sstevel@tonic-gate }; 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate static icmp_type_t icmptypes6[] = { 3180Sstevel@tonic-gate { 0, NULL, 0, NULL }, 3190Sstevel@tonic-gate { ICMP6_DST_UNREACH, icmpredirect6, 3200Sstevel@tonic-gate IST_SZ(icmpredirect6), "unreach" }, 3210Sstevel@tonic-gate { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, 3220Sstevel@tonic-gate { ICMP6_TIME_EXCEEDED, icmptimexceed6, 3230Sstevel@tonic-gate IST_SZ(icmptimexceed6), "timxceed" }, 3240Sstevel@tonic-gate { ICMP6_PARAM_PROB, icmpparamprob6, 3250Sstevel@tonic-gate IST_SZ(icmpparamprob6), "paramprob" }, 3260Sstevel@tonic-gate { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, 3270Sstevel@tonic-gate { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, 3280Sstevel@tonic-gate { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, 3290Sstevel@tonic-gate IST_SZ(icmpquerysubject6), "groupmemberquery" }, 3300Sstevel@tonic-gate { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, 3310Sstevel@tonic-gate { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, 3320Sstevel@tonic-gate { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, 3330Sstevel@tonic-gate { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, 3340Sstevel@tonic-gate { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, 3350Sstevel@tonic-gate { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, 3360Sstevel@tonic-gate { ND_REDIRECT, NULL, 0, "redirect" }, 3370Sstevel@tonic-gate { ICMP6_ROUTER_RENUMBERING, icmprenumber6, 3380Sstevel@tonic-gate IST_SZ(icmprenumber6), "routerrenumber" }, 3390Sstevel@tonic-gate { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, 3400Sstevel@tonic-gate { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, 3410Sstevel@tonic-gate { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, 3420Sstevel@tonic-gate { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, 3430Sstevel@tonic-gate { ICMP6_NI_QUERY, icmpnodeinfo6, 3440Sstevel@tonic-gate IST_SZ(icmpnodeinfo6), "nodeinforequest" }, 3450Sstevel@tonic-gate { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, 3460Sstevel@tonic-gate { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, 3470Sstevel@tonic-gate { MLD6_MTRACE, NULL, 0, "mtracerequest" }, 3480Sstevel@tonic-gate { -2, NULL, 0, NULL } 3490Sstevel@tonic-gate }; 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate static icmp_subtype_t *find_icmpsubtype(type, table, tablesz) 3520Sstevel@tonic-gate int type; 3530Sstevel@tonic-gate icmp_subtype_t *table; 3540Sstevel@tonic-gate size_t tablesz; 3550Sstevel@tonic-gate { 3560Sstevel@tonic-gate icmp_subtype_t *ist; 3570Sstevel@tonic-gate int i; 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate if (tablesz < 2) 3600Sstevel@tonic-gate return NULL; 3610Sstevel@tonic-gate 3620Sstevel@tonic-gate if ((type < 0) || (type > table[tablesz - 2].ist_val)) 3630Sstevel@tonic-gate return NULL; 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate i = type; 3660Sstevel@tonic-gate if (table[type].ist_val == type) 3670Sstevel@tonic-gate return table + type; 3680Sstevel@tonic-gate 3690Sstevel@tonic-gate for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) 3700Sstevel@tonic-gate if (ist->ist_val == type) 3710Sstevel@tonic-gate return ist; 3720Sstevel@tonic-gate return NULL; 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate 3760Sstevel@tonic-gate static icmp_type_t *find_icmptype(type, table, tablesz) 3770Sstevel@tonic-gate int type; 3780Sstevel@tonic-gate icmp_type_t *table; 3790Sstevel@tonic-gate size_t tablesz; 3800Sstevel@tonic-gate { 3810Sstevel@tonic-gate icmp_type_t *it; 3820Sstevel@tonic-gate int i; 3830Sstevel@tonic-gate 3840Sstevel@tonic-gate if (tablesz < 2) 3850Sstevel@tonic-gate return NULL; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate if ((type < 0) || (type > table[tablesz - 2].it_val)) 3880Sstevel@tonic-gate return NULL; 3890Sstevel@tonic-gate 3900Sstevel@tonic-gate i = type; 3910Sstevel@tonic-gate if (table[type].it_val == type) 3920Sstevel@tonic-gate return table + type; 3930Sstevel@tonic-gate 3940Sstevel@tonic-gate for (i = 0, it = table; it->it_val != -2; i++, it++) 3950Sstevel@tonic-gate if (it->it_val == type) 3960Sstevel@tonic-gate return it; 3970Sstevel@tonic-gate return NULL; 3980Sstevel@tonic-gate } 3990Sstevel@tonic-gate 4000Sstevel@tonic-gate 4010Sstevel@tonic-gate static void handlehup(sig) 4020Sstevel@tonic-gate int sig; 4030Sstevel@tonic-gate { 4040Sstevel@tonic-gate FILE *fp; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate signal(SIGHUP, handlehup); 4070Sstevel@tonic-gate if (logfile && (fp = fopen(logfile, "a"))) 4080Sstevel@tonic-gate newlog = fp; 4090Sstevel@tonic-gate if (binarylogfile && (fp = fopen(binarylogfile, "a"))) 4100Sstevel@tonic-gate newbinarylog = fp; 4110Sstevel@tonic-gate init_tabs(); 4120Sstevel@tonic-gate if (conf_file) 4130Sstevel@tonic-gate if (load_config(conf_file) == -1) 4140Sstevel@tonic-gate exit(1); 4150Sstevel@tonic-gate donehup = 1; 4160Sstevel@tonic-gate } 4170Sstevel@tonic-gate 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate static void init_tabs() 4200Sstevel@tonic-gate { 4210Sstevel@tonic-gate struct protoent *p; 4220Sstevel@tonic-gate struct servent *s; 4230Sstevel@tonic-gate char *name, **tab; 4240Sstevel@tonic-gate int port, i; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate if (protocols != NULL) { 4270Sstevel@tonic-gate for (i = 0; i < 256; i++) 4280Sstevel@tonic-gate if (protocols[i] != NULL) { 4290Sstevel@tonic-gate free(protocols[i]); 4300Sstevel@tonic-gate protocols[i] = NULL; 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate free(protocols); 4330Sstevel@tonic-gate protocols = NULL; 4340Sstevel@tonic-gate } 4350Sstevel@tonic-gate protocols = (char **)malloc(256 * sizeof(*protocols)); 4360Sstevel@tonic-gate if (protocols != NULL) { 4370Sstevel@tonic-gate bzero((char *)protocols, 256 * sizeof(*protocols)); 4380Sstevel@tonic-gate 4390Sstevel@tonic-gate setprotoent(1); 4400Sstevel@tonic-gate while ((p = getprotoent()) != NULL) 4410Sstevel@tonic-gate if (p->p_proto >= 0 && p->p_proto <= 255 && 4420Sstevel@tonic-gate p->p_name != NULL && protocols[p->p_proto] == NULL) 4430Sstevel@tonic-gate protocols[p->p_proto] = strdup(p->p_name); 4440Sstevel@tonic-gate endprotoent(); 4450Sstevel@tonic-gate } 4460Sstevel@tonic-gate 4470Sstevel@tonic-gate if (udp_ports != NULL) { 4480Sstevel@tonic-gate for (i = 0; i < 65536; i++) 4490Sstevel@tonic-gate if (udp_ports[i] != NULL) { 4500Sstevel@tonic-gate free(udp_ports[i]); 4510Sstevel@tonic-gate udp_ports[i] = NULL; 4520Sstevel@tonic-gate } 4530Sstevel@tonic-gate free(udp_ports); 4540Sstevel@tonic-gate udp_ports = NULL; 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 4570Sstevel@tonic-gate if (udp_ports != NULL) 4580Sstevel@tonic-gate bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate if (tcp_ports != NULL) { 4610Sstevel@tonic-gate for (i = 0; i < 65536; i++) 4620Sstevel@tonic-gate if (tcp_ports[i] != NULL) { 4630Sstevel@tonic-gate free(tcp_ports[i]); 4640Sstevel@tonic-gate tcp_ports[i] = NULL; 4650Sstevel@tonic-gate } 4660Sstevel@tonic-gate free(tcp_ports); 4670Sstevel@tonic-gate tcp_ports = NULL; 4680Sstevel@tonic-gate } 4690Sstevel@tonic-gate tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 4700Sstevel@tonic-gate if (tcp_ports != NULL) 4710Sstevel@tonic-gate bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 4720Sstevel@tonic-gate 4730Sstevel@tonic-gate setservent(1); 4740Sstevel@tonic-gate while ((s = getservent()) != NULL) { 4750Sstevel@tonic-gate if (s->s_proto == NULL) 4760Sstevel@tonic-gate continue; 4770Sstevel@tonic-gate else if (!strcmp(s->s_proto, "tcp")) { 4780Sstevel@tonic-gate port = ntohs(s->s_port); 4790Sstevel@tonic-gate name = s->s_name; 4800Sstevel@tonic-gate tab = tcp_ports; 4810Sstevel@tonic-gate } else if (!strcmp(s->s_proto, "udp")) { 4820Sstevel@tonic-gate port = ntohs(s->s_port); 4830Sstevel@tonic-gate name = s->s_name; 4840Sstevel@tonic-gate tab = udp_ports; 4850Sstevel@tonic-gate } else 4860Sstevel@tonic-gate continue; 4870Sstevel@tonic-gate if ((port < 0 || port > 65535) || (name == NULL)) 4880Sstevel@tonic-gate continue; 4890Sstevel@tonic-gate if (tab != NULL) 4900Sstevel@tonic-gate tab[port] = strdup(name); 4910Sstevel@tonic-gate } 4920Sstevel@tonic-gate endservent(); 4930Sstevel@tonic-gate } 4940Sstevel@tonic-gate 4950Sstevel@tonic-gate 4960Sstevel@tonic-gate static char *getproto(p) 4970Sstevel@tonic-gate u_int p; 4980Sstevel@tonic-gate { 4990Sstevel@tonic-gate static char pnum[4]; 5000Sstevel@tonic-gate char *s; 5010Sstevel@tonic-gate 5020Sstevel@tonic-gate p &= 0xff; 5030Sstevel@tonic-gate s = protocols ? protocols[p] : NULL; 5040Sstevel@tonic-gate if (s == NULL) { 5050Sstevel@tonic-gate sprintf(pnum, "%u", p); 5060Sstevel@tonic-gate s = pnum; 5070Sstevel@tonic-gate } 5080Sstevel@tonic-gate return s; 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate 5120Sstevel@tonic-gate static int read_log(fd, lenp, buf, bufsize) 5130Sstevel@tonic-gate int fd, bufsize, *lenp; 5140Sstevel@tonic-gate char *buf; 5150Sstevel@tonic-gate { 5160Sstevel@tonic-gate int nr; 5170Sstevel@tonic-gate 5180Sstevel@tonic-gate nr = read(fd, buf, bufsize); 5190Sstevel@tonic-gate if (!nr) 5200Sstevel@tonic-gate return 2; 5210Sstevel@tonic-gate if ((nr < 0) && (errno != EINTR)) 5220Sstevel@tonic-gate return -1; 5230Sstevel@tonic-gate *lenp = nr; 5240Sstevel@tonic-gate return 0; 5250Sstevel@tonic-gate } 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate 5280Sstevel@tonic-gate char *hostname(res, v, ip) 5290Sstevel@tonic-gate int res, v; 5300Sstevel@tonic-gate u_32_t *ip; 5310Sstevel@tonic-gate { 5320Sstevel@tonic-gate # define MAX_INETA 16 5330Sstevel@tonic-gate static char hname[MAXHOSTNAMELEN + MAX_INETA + 3]; 5340Sstevel@tonic-gate #ifdef USE_INET6 5350Sstevel@tonic-gate static char hostbuf[MAXHOSTNAMELEN+1]; 5360Sstevel@tonic-gate #endif 5370Sstevel@tonic-gate struct hostent *hp; 5380Sstevel@tonic-gate struct in_addr ipa; 5390Sstevel@tonic-gate 5400Sstevel@tonic-gate if (v == 4) { 5410Sstevel@tonic-gate ipa.s_addr = *ip; 5420Sstevel@tonic-gate if (!res) 5430Sstevel@tonic-gate return inet_ntoa(ipa); 5440Sstevel@tonic-gate hp = gethostbyaddr((char *)ip, sizeof(*ip), AF_INET); 5450Sstevel@tonic-gate if (!hp) 5460Sstevel@tonic-gate return inet_ntoa(ipa); 5470Sstevel@tonic-gate sprintf(hname, "%.*s[%s]", MAXHOSTNAMELEN, hp->h_name, 5480Sstevel@tonic-gate inet_ntoa(ipa)); 5490Sstevel@tonic-gate return hname; 5500Sstevel@tonic-gate } 5510Sstevel@tonic-gate #ifdef USE_INET6 5520Sstevel@tonic-gate (void) inet_ntop(AF_INET6, ip, hostbuf, sizeof(hostbuf) - 1); 5530Sstevel@tonic-gate hostbuf[MAXHOSTNAMELEN] = '\0'; 5540Sstevel@tonic-gate return hostbuf; 5550Sstevel@tonic-gate #else 5560Sstevel@tonic-gate return "IPv6"; 5570Sstevel@tonic-gate #endif 5580Sstevel@tonic-gate } 5590Sstevel@tonic-gate 5600Sstevel@tonic-gate 5610Sstevel@tonic-gate char *portname(res, proto, port) 5620Sstevel@tonic-gate int res; 5630Sstevel@tonic-gate char *proto; 5640Sstevel@tonic-gate u_int port; 5650Sstevel@tonic-gate { 5660Sstevel@tonic-gate static char pname[8]; 5670Sstevel@tonic-gate char *s; 5680Sstevel@tonic-gate 5690Sstevel@tonic-gate port = ntohs(port); 5700Sstevel@tonic-gate port &= 0xffff; 5710Sstevel@tonic-gate (void) sprintf(pname, "%u", port); 5720Sstevel@tonic-gate if (!res || (opts & OPT_PORTNUM)) 5730Sstevel@tonic-gate return pname; 5740Sstevel@tonic-gate s = NULL; 5750Sstevel@tonic-gate if (!strcmp(proto, "tcp")) 5760Sstevel@tonic-gate s = tcp_ports[port]; 5770Sstevel@tonic-gate else if (!strcmp(proto, "udp")) 5780Sstevel@tonic-gate s = udp_ports[port]; 5790Sstevel@tonic-gate if (s == NULL) 5800Sstevel@tonic-gate s = pname; 5810Sstevel@tonic-gate return s; 5820Sstevel@tonic-gate } 5830Sstevel@tonic-gate 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate static char *icmpname(type, code) 5860Sstevel@tonic-gate u_int type; 5870Sstevel@tonic-gate u_int code; 5880Sstevel@tonic-gate { 5890Sstevel@tonic-gate static char name[80]; 5900Sstevel@tonic-gate icmp_subtype_t *ist; 5910Sstevel@tonic-gate icmp_type_t *it; 5920Sstevel@tonic-gate char *s; 5930Sstevel@tonic-gate 5940Sstevel@tonic-gate s = NULL; 5950Sstevel@tonic-gate it = find_icmptype(type, icmptypes, sizeof(icmptypes) / sizeof(*it)); 5960Sstevel@tonic-gate if (it != NULL) 5970Sstevel@tonic-gate s = it->it_name; 5980Sstevel@tonic-gate 5990Sstevel@tonic-gate if (s == NULL) 6000Sstevel@tonic-gate sprintf(name, "icmptype(%d)/", type); 6010Sstevel@tonic-gate else 6020Sstevel@tonic-gate sprintf(name, "%s/", s); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate ist = NULL; 6050Sstevel@tonic-gate if (it != NULL && it->it_subtable != NULL) 6060Sstevel@tonic-gate ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 6070Sstevel@tonic-gate 6080Sstevel@tonic-gate if (ist != NULL && ist->ist_name != NULL) 6090Sstevel@tonic-gate strcat(name, ist->ist_name); 6100Sstevel@tonic-gate else 6110Sstevel@tonic-gate sprintf(name + strlen(name), "%d", code); 6120Sstevel@tonic-gate 6130Sstevel@tonic-gate return name; 6140Sstevel@tonic-gate } 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate static char *icmpname6(type, code) 6170Sstevel@tonic-gate u_int type; 6180Sstevel@tonic-gate u_int code; 6190Sstevel@tonic-gate { 6200Sstevel@tonic-gate static char name[80]; 6210Sstevel@tonic-gate icmp_subtype_t *ist; 6220Sstevel@tonic-gate icmp_type_t *it; 6230Sstevel@tonic-gate char *s; 6240Sstevel@tonic-gate 6250Sstevel@tonic-gate s = NULL; 6260Sstevel@tonic-gate it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 6270Sstevel@tonic-gate if (it != NULL) 6280Sstevel@tonic-gate s = it->it_name; 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate if (s == NULL) 6310Sstevel@tonic-gate sprintf(name, "icmpv6type(%d)/", type); 6320Sstevel@tonic-gate else 6330Sstevel@tonic-gate sprintf(name, "%s/", s); 6340Sstevel@tonic-gate 6350Sstevel@tonic-gate ist = NULL; 6360Sstevel@tonic-gate if (it != NULL && it->it_subtable != NULL) 6370Sstevel@tonic-gate ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 6380Sstevel@tonic-gate 6390Sstevel@tonic-gate if (ist != NULL && ist->ist_name != NULL) 6400Sstevel@tonic-gate strcat(name, ist->ist_name); 6410Sstevel@tonic-gate else 6420Sstevel@tonic-gate sprintf(name + strlen(name), "%d", code); 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate return name; 6450Sstevel@tonic-gate } 6460Sstevel@tonic-gate 6470Sstevel@tonic-gate 6480Sstevel@tonic-gate void dumphex(log, dopts, buf, len) 6490Sstevel@tonic-gate FILE *log; 6500Sstevel@tonic-gate int dopts; 6510Sstevel@tonic-gate char *buf; 6520Sstevel@tonic-gate int len; 6530Sstevel@tonic-gate { 6540Sstevel@tonic-gate char hline[80]; 6550Sstevel@tonic-gate int i, j, k; 6560Sstevel@tonic-gate u_char *s = (u_char *)buf, *t = (u_char *)hline; 6570Sstevel@tonic-gate 6580Sstevel@tonic-gate if (buf == NULL || len == 0) 6590Sstevel@tonic-gate return; 6600Sstevel@tonic-gate 6610Sstevel@tonic-gate *hline = '\0'; 6620Sstevel@tonic-gate 6630Sstevel@tonic-gate for (i = len, j = 0; i; i--, j++, s++) { 6640Sstevel@tonic-gate if (j && !(j & 0xf)) { 6650Sstevel@tonic-gate *t++ = '\n'; 6660Sstevel@tonic-gate *t = '\0'; 6670Sstevel@tonic-gate if (!(dopts & OPT_SYSLOG)) 6680Sstevel@tonic-gate fputs(hline, log); 6690Sstevel@tonic-gate else 6700Sstevel@tonic-gate syslog(LOG_INFO, "%s", hline); 6710Sstevel@tonic-gate t = (u_char *)hline; 6720Sstevel@tonic-gate *t = '\0'; 6730Sstevel@tonic-gate } 6740Sstevel@tonic-gate sprintf((char *)t, "%02x", *s & 0xff); 6750Sstevel@tonic-gate t += 2; 6760Sstevel@tonic-gate if (!((j + 1) & 0xf)) { 6770Sstevel@tonic-gate s -= 15; 6780Sstevel@tonic-gate sprintf((char *)t, " "); 6790Sstevel@tonic-gate t += 8; 6800Sstevel@tonic-gate for (k = 16; k; k--, s++) 6810Sstevel@tonic-gate *t++ = (isprint(*s) ? *s : '.'); 6820Sstevel@tonic-gate s--; 6830Sstevel@tonic-gate } 6840Sstevel@tonic-gate 6850Sstevel@tonic-gate if ((j + 1) & 0xf) 6860Sstevel@tonic-gate *t++ = ' ';; 6870Sstevel@tonic-gate } 6880Sstevel@tonic-gate 6890Sstevel@tonic-gate if (j & 0xf) { 6900Sstevel@tonic-gate for (k = 16 - (j & 0xf); k; k--) { 6910Sstevel@tonic-gate *t++ = ' '; 6920Sstevel@tonic-gate *t++ = ' '; 6930Sstevel@tonic-gate *t++ = ' '; 6940Sstevel@tonic-gate } 6950Sstevel@tonic-gate sprintf((char *)t, " "); 6960Sstevel@tonic-gate t += 7; 6970Sstevel@tonic-gate s -= j & 0xf; 6980Sstevel@tonic-gate for (k = j & 0xf; k; k--, s++) 6990Sstevel@tonic-gate *t++ = (isprint(*s) ? *s : '.'); 7000Sstevel@tonic-gate *t++ = '\n'; 7010Sstevel@tonic-gate *t = '\0'; 7020Sstevel@tonic-gate } 7030Sstevel@tonic-gate if (!(dopts & OPT_SYSLOG)) { 7040Sstevel@tonic-gate fputs(hline, log); 7050Sstevel@tonic-gate fflush(log); 7060Sstevel@tonic-gate } else 7070Sstevel@tonic-gate syslog(LOG_INFO, "%s", hline); 7080Sstevel@tonic-gate } 7090Sstevel@tonic-gate 7100Sstevel@tonic-gate 7110Sstevel@tonic-gate static struct tm *get_tm(sec) 7120Sstevel@tonic-gate #ifdef __hpux 7130Sstevel@tonic-gate u_32_t sec; 7140Sstevel@tonic-gate #else 7150Sstevel@tonic-gate time_t sec; 7160Sstevel@tonic-gate #endif 7170Sstevel@tonic-gate { 7180Sstevel@tonic-gate struct tm *tm; 7190Sstevel@tonic-gate time_t t; 7200Sstevel@tonic-gate 7210Sstevel@tonic-gate t = sec; 7220Sstevel@tonic-gate tm = localtime(&t); 7230Sstevel@tonic-gate return tm; 7240Sstevel@tonic-gate } 7250Sstevel@tonic-gate 7260Sstevel@tonic-gate static void print_natlog(log, buf, blen) 7270Sstevel@tonic-gate FILE *log; 7280Sstevel@tonic-gate char *buf; 7290Sstevel@tonic-gate int blen; 7300Sstevel@tonic-gate { 7310Sstevel@tonic-gate struct natlog *nl; 7320Sstevel@tonic-gate iplog_t *ipl = (iplog_t *)buf; 7330Sstevel@tonic-gate char *t = line; 7340Sstevel@tonic-gate struct tm *tm; 7350Sstevel@tonic-gate int res, i, len; 7360Sstevel@tonic-gate char *proto; 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 7390Sstevel@tonic-gate res = (opts & OPT_RESOLVE) ? 1 : 0; 7400Sstevel@tonic-gate tm = get_tm(ipl->ipl_sec); 7410Sstevel@tonic-gate len = sizeof(line); 7420Sstevel@tonic-gate if (!(opts & OPT_SYSLOG)) { 7430Sstevel@tonic-gate (void) strftime(t, len, "%d/%m/%Y ", tm); 7440Sstevel@tonic-gate i = strlen(t); 7450Sstevel@tonic-gate len -= i; 7460Sstevel@tonic-gate t += i; 7470Sstevel@tonic-gate } 7480Sstevel@tonic-gate (void) strftime(t, len, "%T", tm); 7490Sstevel@tonic-gate t += strlen(t); 7500Sstevel@tonic-gate (void) sprintf(t, ".%-.6ld @%hd ", ipl->ipl_usec, nl->nl_rule + 1); 7510Sstevel@tonic-gate t += strlen(t); 7520Sstevel@tonic-gate 7530Sstevel@tonic-gate if (nl->nl_type == NL_NEWMAP) 7540Sstevel@tonic-gate strcpy(t, "NAT:MAP "); 7550Sstevel@tonic-gate else if (nl->nl_type == NL_NEWRDR) 7560Sstevel@tonic-gate strcpy(t, "NAT:RDR "); 7570Sstevel@tonic-gate else if (nl->nl_type == NL_FLUSH) 7580Sstevel@tonic-gate strcpy(t, "NAT:FLUSH "); 7590Sstevel@tonic-gate else if (nl->nl_type == NL_EXPIRE) 7600Sstevel@tonic-gate strcpy(t, "NAT:EXPIRE "); 7610Sstevel@tonic-gate else if (nl->nl_type == NL_NEWBIMAP) 7620Sstevel@tonic-gate strcpy(t, "NAT:BIMAP "); 7630Sstevel@tonic-gate else if (nl->nl_type == NL_NEWBLOCK) 7640Sstevel@tonic-gate strcpy(t, "NAT:MAPBLOCK "); 7650Sstevel@tonic-gate else if (nl->nl_type == NL_CLONE) 7660Sstevel@tonic-gate strcpy(t, "NAT:CLONE "); 7670Sstevel@tonic-gate else 7680Sstevel@tonic-gate sprintf(t, "Type: %d ", nl->nl_type); 7690Sstevel@tonic-gate t += strlen(t); 7700Sstevel@tonic-gate 7710Sstevel@tonic-gate proto = getproto(nl->nl_p); 7720Sstevel@tonic-gate 7730Sstevel@tonic-gate (void) sprintf(t, "%s,%s <- -> ", HOSTNAME_V4(res, nl->nl_inip), 7740Sstevel@tonic-gate portname(res, proto, (u_int)nl->nl_inport)); 7750Sstevel@tonic-gate t += strlen(t); 7760Sstevel@tonic-gate (void) sprintf(t, "%s,%s ", HOSTNAME_V4(res, nl->nl_outip), 7770Sstevel@tonic-gate portname(res, proto, (u_int)nl->nl_outport)); 7780Sstevel@tonic-gate t += strlen(t); 7790Sstevel@tonic-gate (void) sprintf(t, "[%s,%s]", HOSTNAME_V4(res, nl->nl_origip), 7800Sstevel@tonic-gate portname(res, proto, (u_int)nl->nl_origport)); 7810Sstevel@tonic-gate t += strlen(t); 7820Sstevel@tonic-gate if (nl->nl_type == NL_EXPIRE) { 7830Sstevel@tonic-gate #ifdef USE_QUAD_T 7840Sstevel@tonic-gate (void) sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 7850Sstevel@tonic-gate (long long)nl->nl_pkts[0], 7860Sstevel@tonic-gate (long long)nl->nl_pkts[1], 7870Sstevel@tonic-gate (long long)nl->nl_bytes[0], 7880Sstevel@tonic-gate (long long)nl->nl_bytes[1]); 7890Sstevel@tonic-gate #else 7900Sstevel@tonic-gate (void) sprintf(t, " Pkts %ld Bytes %ld", 7910Sstevel@tonic-gate nl->nl_pkts[0], nl->nl_pkts[1], 7920Sstevel@tonic-gate nl->nl_bytes[0], nl->nl_bytes[1]); 7930Sstevel@tonic-gate #endif 7940Sstevel@tonic-gate t += strlen(t); 7950Sstevel@tonic-gate } 7960Sstevel@tonic-gate 7970Sstevel@tonic-gate *t++ = '\n'; 7980Sstevel@tonic-gate *t++ = '\0'; 7990Sstevel@tonic-gate if (opts & OPT_SYSLOG) 8000Sstevel@tonic-gate syslog(LOG_INFO, "%s", line); 8010Sstevel@tonic-gate else 8020Sstevel@tonic-gate (void) fprintf(log, "%s", line); 8030Sstevel@tonic-gate } 8040Sstevel@tonic-gate 8050Sstevel@tonic-gate 8060Sstevel@tonic-gate static void print_statelog(log, buf, blen) 8070Sstevel@tonic-gate FILE *log; 8080Sstevel@tonic-gate char *buf; 8090Sstevel@tonic-gate int blen; 8100Sstevel@tonic-gate { 8110Sstevel@tonic-gate struct ipslog *sl; 8120Sstevel@tonic-gate iplog_t *ipl = (iplog_t *)buf; 8130Sstevel@tonic-gate char *t = line, *proto; 8140Sstevel@tonic-gate struct tm *tm; 8150Sstevel@tonic-gate int res, i, len; 8160Sstevel@tonic-gate 8170Sstevel@tonic-gate sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 8180Sstevel@tonic-gate res = (opts & OPT_RESOLVE) ? 1 : 0; 8190Sstevel@tonic-gate tm = get_tm(ipl->ipl_sec); 8200Sstevel@tonic-gate len = sizeof(line); 8210Sstevel@tonic-gate if (!(opts & OPT_SYSLOG)) { 8220Sstevel@tonic-gate (void) strftime(t, len, "%d/%m/%Y ", tm); 8230Sstevel@tonic-gate i = strlen(t); 8240Sstevel@tonic-gate len -= i; 8250Sstevel@tonic-gate t += i; 8260Sstevel@tonic-gate } 8270Sstevel@tonic-gate (void) strftime(t, len, "%T", tm); 8280Sstevel@tonic-gate t += strlen(t); 8290Sstevel@tonic-gate (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 8300Sstevel@tonic-gate t += strlen(t); 8310Sstevel@tonic-gate 8320Sstevel@tonic-gate if (sl->isl_type == ISL_NEW) 8330Sstevel@tonic-gate strcpy(t, "STATE:NEW "); 8340Sstevel@tonic-gate else if (sl->isl_type == ISL_CLONE) 8350Sstevel@tonic-gate strcpy(t, "STATE:CLONED "); 8360Sstevel@tonic-gate else if (sl->isl_type == ISL_EXPIRE) { 8370Sstevel@tonic-gate if ((sl->isl_p == IPPROTO_TCP) && 8380Sstevel@tonic-gate (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 8390Sstevel@tonic-gate sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 8400Sstevel@tonic-gate strcpy(t, "STATE:CLOSE "); 8410Sstevel@tonic-gate else 8420Sstevel@tonic-gate strcpy(t, "STATE:EXPIRE "); 8430Sstevel@tonic-gate } else if (sl->isl_type == ISL_FLUSH) 8440Sstevel@tonic-gate strcpy(t, "STATE:FLUSH "); 8450Sstevel@tonic-gate else if (sl->isl_type == ISL_INTERMEDIATE) 8460Sstevel@tonic-gate strcpy(t, "STATE:INTERMEDIATE "); 8470Sstevel@tonic-gate else if (sl->isl_type == ISL_REMOVE) 8480Sstevel@tonic-gate strcpy(t, "STATE:REMOVE "); 8490Sstevel@tonic-gate else if (sl->isl_type == ISL_KILLED) 8500Sstevel@tonic-gate strcpy(t, "STATE:KILLED "); 8510Sstevel@tonic-gate else 8520Sstevel@tonic-gate sprintf(t, "Type: %d ", sl->isl_type); 8530Sstevel@tonic-gate t += strlen(t); 8540Sstevel@tonic-gate 8550Sstevel@tonic-gate proto = getproto(sl->isl_p); 8560Sstevel@tonic-gate 8570Sstevel@tonic-gate if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 8580Sstevel@tonic-gate (void) sprintf(t, "%s,%s -> ", 8590Sstevel@tonic-gate hostname(res, sl->isl_v, (u_32_t *)&sl->isl_src), 8600Sstevel@tonic-gate portname(res, proto, (u_int)sl->isl_sport)); 8610Sstevel@tonic-gate t += strlen(t); 8620Sstevel@tonic-gate (void) sprintf(t, "%s,%s PR %s", 8630Sstevel@tonic-gate hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 8640Sstevel@tonic-gate portname(res, proto, (u_int)sl->isl_dport), proto); 8650Sstevel@tonic-gate } else if (sl->isl_p == IPPROTO_ICMP) { 8660Sstevel@tonic-gate (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 8670Sstevel@tonic-gate (u_32_t *)&sl->isl_src)); 8680Sstevel@tonic-gate t += strlen(t); 8690Sstevel@tonic-gate (void) sprintf(t, "%s PR icmp %d", 8700Sstevel@tonic-gate hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 8710Sstevel@tonic-gate sl->isl_itype); 8720Sstevel@tonic-gate } else if (sl->isl_p == IPPROTO_ICMPV6) { 8730Sstevel@tonic-gate (void) sprintf(t, "%s -> ", hostname(res, sl->isl_v, 8740Sstevel@tonic-gate (u_32_t *)&sl->isl_src)); 8750Sstevel@tonic-gate t += strlen(t); 8760Sstevel@tonic-gate (void) sprintf(t, "%s PR icmpv6 %d", 8770Sstevel@tonic-gate hostname(res, sl->isl_v, (u_32_t *)&sl->isl_dst), 8780Sstevel@tonic-gate sl->isl_itype); 8790Sstevel@tonic-gate } 8800Sstevel@tonic-gate t += strlen(t); 8810Sstevel@tonic-gate if (sl->isl_tag != FR_NOLOGTAG) { 8820Sstevel@tonic-gate (void) sprintf(t, " tag %u", sl->isl_tag); 8830Sstevel@tonic-gate t += strlen(t); 8840Sstevel@tonic-gate } 8850Sstevel@tonic-gate if (sl->isl_type != ISL_NEW) { 8860Sstevel@tonic-gate sprintf(t, 8870Sstevel@tonic-gate #ifdef USE_QUAD_T 8880Sstevel@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", 8890Sstevel@tonic-gate #else 8900Sstevel@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", 8910Sstevel@tonic-gate #endif 8920Sstevel@tonic-gate sl->isl_pkts[0], sl->isl_bytes[0], 8930Sstevel@tonic-gate sl->isl_pkts[1], sl->isl_bytes[1], 8940Sstevel@tonic-gate sl->isl_pkts[2], sl->isl_bytes[2], 8950Sstevel@tonic-gate sl->isl_pkts[3], sl->isl_bytes[3]); 8960Sstevel@tonic-gate 8970Sstevel@tonic-gate t += strlen(t); 8980Sstevel@tonic-gate } 8990Sstevel@tonic-gate 9000Sstevel@tonic-gate *t++ = '\n'; 9010Sstevel@tonic-gate *t++ = '\0'; 9020Sstevel@tonic-gate if (opts & OPT_SYSLOG) 9030Sstevel@tonic-gate syslog(LOG_INFO, "%s", line); 9040Sstevel@tonic-gate else 9050Sstevel@tonic-gate (void) fprintf(log, "%s", line); 9060Sstevel@tonic-gate } 9070Sstevel@tonic-gate 9080Sstevel@tonic-gate 9090Sstevel@tonic-gate static void print_log(logtype, log, buf, blen) 9100Sstevel@tonic-gate FILE *log; 9110Sstevel@tonic-gate char *buf; 9120Sstevel@tonic-gate int logtype, blen; 9130Sstevel@tonic-gate { 9140Sstevel@tonic-gate iplog_t *ipl; 9150Sstevel@tonic-gate char *bp = NULL, *bpo = NULL; 9160Sstevel@tonic-gate int psize; 9170Sstevel@tonic-gate 9180Sstevel@tonic-gate while (blen > 0) { 9190Sstevel@tonic-gate ipl = (iplog_t *)buf; 9200Sstevel@tonic-gate if ((u_long)ipl & (sizeof(long)-1)) { 9210Sstevel@tonic-gate if (bp) 9220Sstevel@tonic-gate bpo = bp; 9230Sstevel@tonic-gate bp = (char *)malloc(blen); 924*1448Sschuster if (bp == NULL) { 925*1448Sschuster perror("malloc"); 926*1448Sschuster exit(1); 927*1448Sschuster } 9280Sstevel@tonic-gate bcopy((char *)ipl, bp, blen); 9290Sstevel@tonic-gate if (bpo) { 9300Sstevel@tonic-gate free(bpo); 9310Sstevel@tonic-gate bpo = NULL; 9320Sstevel@tonic-gate } 9330Sstevel@tonic-gate buf = bp; 9340Sstevel@tonic-gate continue; 9350Sstevel@tonic-gate } 9360Sstevel@tonic-gate 9370Sstevel@tonic-gate psize = ipl->ipl_dsize; 9380Sstevel@tonic-gate if (psize > blen) 9390Sstevel@tonic-gate break; 9400Sstevel@tonic-gate 9410Sstevel@tonic-gate if (binarylog) { 9420Sstevel@tonic-gate fwrite(buf, psize, 1, binarylog); 9430Sstevel@tonic-gate fflush(binarylog); 9440Sstevel@tonic-gate } 9450Sstevel@tonic-gate 9460Sstevel@tonic-gate if (logtype == IPL_LOGIPF) { 9470Sstevel@tonic-gate if (ipl->ipl_magic != IPL_MAGIC) { 9480Sstevel@tonic-gate /* invalid data or out of sync */ 9490Sstevel@tonic-gate break; 9500Sstevel@tonic-gate } 9510Sstevel@tonic-gate print_ipflog(log, buf, psize); 9520Sstevel@tonic-gate 9530Sstevel@tonic-gate } else if (logtype == IPL_LOGNAT) { 9540Sstevel@tonic-gate if (ipl->ipl_magic != IPL_MAGIC) { 9550Sstevel@tonic-gate /* invalid data or out of sync */ 9560Sstevel@tonic-gate break; 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate print_natlog(log, buf, psize); 9590Sstevel@tonic-gate 9600Sstevel@tonic-gate } else if (logtype == IPL_LOGSTATE) { 9610Sstevel@tonic-gate if (ipl->ipl_magic != IPL_MAGIC) { 9620Sstevel@tonic-gate /* invalid data or out of sync */ 9630Sstevel@tonic-gate break; 9640Sstevel@tonic-gate } 9650Sstevel@tonic-gate print_statelog(log, buf, psize); 9660Sstevel@tonic-gate } 9670Sstevel@tonic-gate 9680Sstevel@tonic-gate blen -= psize; 9690Sstevel@tonic-gate buf += psize; 9700Sstevel@tonic-gate } 9710Sstevel@tonic-gate if (bp) 9720Sstevel@tonic-gate free(bp); 9730Sstevel@tonic-gate return; 9740Sstevel@tonic-gate } 9750Sstevel@tonic-gate 9760Sstevel@tonic-gate 9770Sstevel@tonic-gate static void print_ipflog(log, buf, blen) 9780Sstevel@tonic-gate FILE *log; 9790Sstevel@tonic-gate char *buf; 9800Sstevel@tonic-gate int blen; 9810Sstevel@tonic-gate { 9820Sstevel@tonic-gate tcphdr_t *tp; 9830Sstevel@tonic-gate struct icmp *ic; 9840Sstevel@tonic-gate struct icmp *icmp; 9850Sstevel@tonic-gate struct tm *tm; 9860Sstevel@tonic-gate char *t, *proto; 9870Sstevel@tonic-gate int i, v, lvl, res, len, off, plen, ipoff; 9880Sstevel@tonic-gate u_32_t *s, *d, cmdflags; 9890Sstevel@tonic-gate ip_t *ipc, *ip; 9900Sstevel@tonic-gate u_short hl, p; 9910Sstevel@tonic-gate ipflog_t *ipf; 9920Sstevel@tonic-gate iplog_t *ipl; 9930Sstevel@tonic-gate #ifdef USE_INET6 9940Sstevel@tonic-gate ip6_t *ip6; 9950Sstevel@tonic-gate #endif 9960Sstevel@tonic-gate 9970Sstevel@tonic-gate ipl = (iplog_t *)buf; 9980Sstevel@tonic-gate ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 9990Sstevel@tonic-gate ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 10000Sstevel@tonic-gate v = IP_V(ip); 10010Sstevel@tonic-gate res = (opts & OPT_RESOLVE) ? 1 : 0; 10020Sstevel@tonic-gate t = line; 10030Sstevel@tonic-gate *t = '\0'; 10040Sstevel@tonic-gate tm = get_tm(ipl->ipl_sec); 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate len = sizeof(line); 10070Sstevel@tonic-gate if (!(opts & OPT_SYSLOG)) { 10080Sstevel@tonic-gate (void) strftime(t, len, "%d/%m/%Y ", tm); 10090Sstevel@tonic-gate i = strlen(t); 10100Sstevel@tonic-gate len -= i; 10110Sstevel@tonic-gate t += i; 10120Sstevel@tonic-gate } 10130Sstevel@tonic-gate (void) strftime(t, len, "%T", tm); 10140Sstevel@tonic-gate t += strlen(t); 10150Sstevel@tonic-gate (void) sprintf(t, ".%-.6ld ", ipl->ipl_usec); 10160Sstevel@tonic-gate t += strlen(t); 10170Sstevel@tonic-gate if (ipl->ipl_count > 1) { 10180Sstevel@tonic-gate (void) sprintf(t, "%dx ", ipl->ipl_count); 10190Sstevel@tonic-gate t += strlen(t); 10200Sstevel@tonic-gate } 10210Sstevel@tonic-gate #if (defined(MENTAT) || \ 10220Sstevel@tonic-gate (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 10230Sstevel@tonic-gate (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) 10240Sstevel@tonic-gate { 10250Sstevel@tonic-gate char ifname[sizeof(ipf->fl_ifname) + 1]; 10260Sstevel@tonic-gate 10270Sstevel@tonic-gate strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 10280Sstevel@tonic-gate ifname[sizeof(ipf->fl_ifname)] = '\0'; 10290Sstevel@tonic-gate (void) sprintf(t, "%s", ifname); 10300Sstevel@tonic-gate t += strlen(t); 10310Sstevel@tonic-gate # if defined(MENTAT) 10320Sstevel@tonic-gate if (isalpha(*(t - 1))) { 10330Sstevel@tonic-gate sprintf(t, "%d", ipf->fl_unit); 10340Sstevel@tonic-gate t += strlen(t); 10350Sstevel@tonic-gate } 10360Sstevel@tonic-gate # endif 10370Sstevel@tonic-gate } 10380Sstevel@tonic-gate #else 10390Sstevel@tonic-gate for (len = 0; len < 3; len++) 10400Sstevel@tonic-gate if (ipf->fl_ifname[len] == '\0') 10410Sstevel@tonic-gate break; 10420Sstevel@tonic-gate if (ipf->fl_ifname[len]) 10430Sstevel@tonic-gate len++; 10440Sstevel@tonic-gate (void) sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit); 10450Sstevel@tonic-gate t += strlen(t); 10460Sstevel@tonic-gate #endif 10470Sstevel@tonic-gate if ((ipf->fl_group[0] == -1) && (ipf->fl_group[1] == '\0')) 10480Sstevel@tonic-gate strcat(t, " @-1:"); 10490Sstevel@tonic-gate else if (ipf->fl_group[0] == '\0') 10500Sstevel@tonic-gate (void) strcpy(t, " @0:"); 10510Sstevel@tonic-gate else 10520Sstevel@tonic-gate (void) sprintf(t, " @%s:", ipf->fl_group); 10530Sstevel@tonic-gate t += strlen(t); 10540Sstevel@tonic-gate if (ipf->fl_rule == 0xffffffff) 10550Sstevel@tonic-gate strcat(t, "-1 "); 10560Sstevel@tonic-gate else 10570Sstevel@tonic-gate (void) sprintf(t, "%u ", ipf->fl_rule + 1); 10580Sstevel@tonic-gate t += strlen(t); 10590Sstevel@tonic-gate 10600Sstevel@tonic-gate lvl = LOG_NOTICE; 10610Sstevel@tonic-gate 10620Sstevel@tonic-gate if (ipf->fl_lflags & FI_SHORT) { 10630Sstevel@tonic-gate *t++ = 'S'; 10640Sstevel@tonic-gate lvl = LOG_ERR; 10650Sstevel@tonic-gate } 10660Sstevel@tonic-gate 10670Sstevel@tonic-gate cmdflags = ipf->fl_flags & FR_CMDMASK; 10680Sstevel@tonic-gate if (FR_ISPASS(ipf->fl_flags)) { 10690Sstevel@tonic-gate if (ipf->fl_flags & FR_LOGP) 10700Sstevel@tonic-gate *t++ = 'p'; 10710Sstevel@tonic-gate else 10720Sstevel@tonic-gate *t++ = 'P'; 10730Sstevel@tonic-gate } else if (FR_ISBLOCK(ipf->fl_flags)) { 10740Sstevel@tonic-gate if (ipf->fl_flags & FR_LOGB) 10750Sstevel@tonic-gate *t++ = 'b'; 10760Sstevel@tonic-gate else 10770Sstevel@tonic-gate *t++ = 'B'; 10780Sstevel@tonic-gate lvl = LOG_WARNING; 10790Sstevel@tonic-gate } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 10800Sstevel@tonic-gate *t++ = 'L'; 10810Sstevel@tonic-gate lvl = LOG_INFO; 10820Sstevel@tonic-gate } else if (ipf->fl_flags & FF_LOGNOMATCH) { 10830Sstevel@tonic-gate *t++ = 'n'; 10840Sstevel@tonic-gate } else { 10850Sstevel@tonic-gate *t++ = '?'; 10860Sstevel@tonic-gate lvl = LOG_EMERG; 10870Sstevel@tonic-gate } 10880Sstevel@tonic-gate if (ipf->fl_loglevel != 0xffff) 10890Sstevel@tonic-gate lvl = ipf->fl_loglevel; 10900Sstevel@tonic-gate *t++ = ' '; 10910Sstevel@tonic-gate *t = '\0'; 10920Sstevel@tonic-gate 10930Sstevel@tonic-gate if (v == 6) { 10940Sstevel@tonic-gate #ifdef USE_INET6 10950Sstevel@tonic-gate off = 0; 10960Sstevel@tonic-gate ipoff = 0; 10970Sstevel@tonic-gate hl = sizeof(ip6_t); 10980Sstevel@tonic-gate ip6 = (ip6_t *)ip; 10990Sstevel@tonic-gate p = (u_short)ip6->ip6_nxt; 11000Sstevel@tonic-gate s = (u_32_t *)&ip6->ip6_src; 11010Sstevel@tonic-gate d = (u_32_t *)&ip6->ip6_dst; 11020Sstevel@tonic-gate plen = ntohs(ip6->ip6_plen); 11030Sstevel@tonic-gate #else 11040Sstevel@tonic-gate sprintf(t, "ipv6"); 11050Sstevel@tonic-gate goto printipflog; 11060Sstevel@tonic-gate #endif 11070Sstevel@tonic-gate } else if (v == 4) { 11080Sstevel@tonic-gate hl = IP_HL(ip) << 2; 11090Sstevel@tonic-gate ipoff = ip->ip_off; 11100Sstevel@tonic-gate off = ipoff & IP_OFFMASK; 11110Sstevel@tonic-gate p = (u_short)ip->ip_p; 11120Sstevel@tonic-gate s = (u_32_t *)&ip->ip_src; 11130Sstevel@tonic-gate d = (u_32_t *)&ip->ip_dst; 11140Sstevel@tonic-gate plen = ip->ip_len; 11150Sstevel@tonic-gate } else { 11160Sstevel@tonic-gate goto printipflog; 11170Sstevel@tonic-gate } 11180Sstevel@tonic-gate proto = getproto(p); 11190Sstevel@tonic-gate 11200Sstevel@tonic-gate if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 11210Sstevel@tonic-gate tp = (tcphdr_t *)((char *)ip + hl); 11220Sstevel@tonic-gate if (!(ipf->fl_lflags & FI_SHORT)) { 11230Sstevel@tonic-gate (void) sprintf(t, "%s,%s -> ", hostname(res, v, s), 11240Sstevel@tonic-gate portname(res, proto, (u_int)tp->th_sport)); 11250Sstevel@tonic-gate t += strlen(t); 11260Sstevel@tonic-gate (void) sprintf(t, "%s,%s PR %s len %hu %hu", 11270Sstevel@tonic-gate hostname(res, v, d), 11280Sstevel@tonic-gate portname(res, proto, (u_int)tp->th_dport), 11290Sstevel@tonic-gate proto, hl, plen); 11300Sstevel@tonic-gate t += strlen(t); 11310Sstevel@tonic-gate 11320Sstevel@tonic-gate if (p == IPPROTO_TCP) { 11330Sstevel@tonic-gate *t++ = ' '; 11340Sstevel@tonic-gate *t++ = '-'; 11350Sstevel@tonic-gate for (i = 0; tcpfl[i].value; i++) 11360Sstevel@tonic-gate if (tp->th_flags & tcpfl[i].value) 11370Sstevel@tonic-gate *t++ = tcpfl[i].flag; 11380Sstevel@tonic-gate if (opts & OPT_VERBOSE) { 11390Sstevel@tonic-gate (void) sprintf(t, " %lu %lu %hu", 11400Sstevel@tonic-gate (u_long)(ntohl(tp->th_seq)), 11410Sstevel@tonic-gate (u_long)(ntohl(tp->th_ack)), 11420Sstevel@tonic-gate ntohs(tp->th_win)); 11430Sstevel@tonic-gate t += strlen(t); 11440Sstevel@tonic-gate } 11450Sstevel@tonic-gate } 11460Sstevel@tonic-gate *t = '\0'; 11470Sstevel@tonic-gate } else { 11480Sstevel@tonic-gate (void) sprintf(t, "%s -> ", hostname(res, v, s)); 11490Sstevel@tonic-gate t += strlen(t); 11500Sstevel@tonic-gate (void) sprintf(t, "%s PR %s len %hu %hu", 11510Sstevel@tonic-gate hostname(res, v, d), proto, hl, plen); 11520Sstevel@tonic-gate } 11530Sstevel@tonic-gate } else if ((p == IPPROTO_ICMPV6) && !off && (v == 6)) { 11540Sstevel@tonic-gate ic = (struct icmp *)((char *)ip + hl); 11550Sstevel@tonic-gate (void) sprintf(t, "%s -> ", hostname(res, v, s)); 11560Sstevel@tonic-gate t += strlen(t); 11570Sstevel@tonic-gate (void) sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 11580Sstevel@tonic-gate hostname(res, v, d), hl, plen, 11590Sstevel@tonic-gate icmpname6(ic->icmp_type, ic->icmp_code)); 11600Sstevel@tonic-gate } else if ((p == IPPROTO_ICMP) && !off && (v == 4)) { 11610Sstevel@tonic-gate ic = (struct icmp *)((char *)ip + hl); 11620Sstevel@tonic-gate (void) sprintf(t, "%s -> ", hostname(res, v, s)); 11630Sstevel@tonic-gate t += strlen(t); 11640Sstevel@tonic-gate (void) sprintf(t, "%s PR icmp len %hu %hu icmp %s", 11650Sstevel@tonic-gate hostname(res, v, d), hl, plen, 11660Sstevel@tonic-gate icmpname(ic->icmp_type, ic->icmp_code)); 11670Sstevel@tonic-gate if (ic->icmp_type == ICMP_UNREACH || 11680Sstevel@tonic-gate ic->icmp_type == ICMP_SOURCEQUENCH || 11690Sstevel@tonic-gate ic->icmp_type == ICMP_PARAMPROB || 11700Sstevel@tonic-gate ic->icmp_type == ICMP_REDIRECT || 11710Sstevel@tonic-gate ic->icmp_type == ICMP_TIMXCEED) { 11720Sstevel@tonic-gate ipc = &ic->icmp_ip; 11730Sstevel@tonic-gate i = ntohs(ipc->ip_len); 11740Sstevel@tonic-gate /* 11750Sstevel@tonic-gate * XXX - try to guess endian of ip_len in ICMP 11760Sstevel@tonic-gate * returned data. 11770Sstevel@tonic-gate */ 11780Sstevel@tonic-gate if (i > 1500) 11790Sstevel@tonic-gate i = ipc->ip_len; 11800Sstevel@tonic-gate ipoff = ntohs(ipc->ip_off); 11810Sstevel@tonic-gate proto = getproto(ipc->ip_p); 11820Sstevel@tonic-gate 11830Sstevel@tonic-gate if (!(ipoff & IP_OFFMASK) && 11840Sstevel@tonic-gate ((ipc->ip_p == IPPROTO_TCP) || 11850Sstevel@tonic-gate (ipc->ip_p == IPPROTO_UDP))) { 11860Sstevel@tonic-gate tp = (tcphdr_t *)((char *)ipc + hl); 11870Sstevel@tonic-gate t += strlen(t); 11880Sstevel@tonic-gate (void) sprintf(t, " for %s,%s -", 11890Sstevel@tonic-gate HOSTNAME_V4(res, ipc->ip_src), 11900Sstevel@tonic-gate portname(res, proto, 11910Sstevel@tonic-gate (u_int)tp->th_sport)); 11920Sstevel@tonic-gate t += strlen(t); 11930Sstevel@tonic-gate (void) sprintf(t, " %s,%s PR %s len %hu %hu", 11940Sstevel@tonic-gate HOSTNAME_V4(res, ipc->ip_dst), 11950Sstevel@tonic-gate portname(res, proto, 11960Sstevel@tonic-gate (u_int)tp->th_dport), 11970Sstevel@tonic-gate proto, IP_HL(ipc) << 2, i); 11980Sstevel@tonic-gate } else if (!(ipoff & IP_OFFMASK) && 11990Sstevel@tonic-gate (ipc->ip_p == IPPROTO_ICMP)) { 12000Sstevel@tonic-gate icmp = (icmphdr_t *)((char *)ipc + hl); 12010Sstevel@tonic-gate 12020Sstevel@tonic-gate t += strlen(t); 12030Sstevel@tonic-gate (void) sprintf(t, " for %s -", 12040Sstevel@tonic-gate HOSTNAME_V4(res, ipc->ip_src)); 12050Sstevel@tonic-gate t += strlen(t); 12060Sstevel@tonic-gate (void) sprintf(t, 12070Sstevel@tonic-gate " %s PR icmp len %hu %hu icmp %d/%d", 12080Sstevel@tonic-gate HOSTNAME_V4(res, ipc->ip_dst), 12090Sstevel@tonic-gate IP_HL(ipc) << 2, i, 12100Sstevel@tonic-gate icmp->icmp_type, icmp->icmp_code); 12110Sstevel@tonic-gate } else { 12120Sstevel@tonic-gate t += strlen(t); 12130Sstevel@tonic-gate (void) sprintf(t, " for %s -", 12140Sstevel@tonic-gate HOSTNAME_V4(res, ipc->ip_src)); 12150Sstevel@tonic-gate t += strlen(t); 12160Sstevel@tonic-gate (void) sprintf(t, " %s PR %s len %hu (%hu)", 12170Sstevel@tonic-gate HOSTNAME_V4(res, ipc->ip_dst), proto, 12180Sstevel@tonic-gate IP_HL(ipc) << 2, i); 12190Sstevel@tonic-gate t += strlen(t); 12200Sstevel@tonic-gate if (ipoff & IP_OFFMASK) { 12210Sstevel@tonic-gate (void) sprintf(t, " frag %s%s%hu@%hu", 12220Sstevel@tonic-gate ipoff & IP_MF ? "+" : "", 12230Sstevel@tonic-gate ipoff & IP_DF ? "-" : "", 12240Sstevel@tonic-gate i - (IP_HL(ipc) << 2), 12250Sstevel@tonic-gate (ipoff & IP_OFFMASK) << 3); 12260Sstevel@tonic-gate } 12270Sstevel@tonic-gate } 12280Sstevel@tonic-gate 12290Sstevel@tonic-gate } 12300Sstevel@tonic-gate } else { 12310Sstevel@tonic-gate (void) sprintf(t, "%s -> ", hostname(res, v, s)); 12320Sstevel@tonic-gate t += strlen(t); 12330Sstevel@tonic-gate (void) sprintf(t, "%s PR %s len %hu (%hu)", 12340Sstevel@tonic-gate hostname(res, v, d), proto, hl, plen); 12350Sstevel@tonic-gate t += strlen(t); 12360Sstevel@tonic-gate if (off & IP_OFFMASK) 12370Sstevel@tonic-gate (void) sprintf(t, " frag %s%s%hu@%hu", 12380Sstevel@tonic-gate ipoff & IP_MF ? "+" : "", 12390Sstevel@tonic-gate ipoff & IP_DF ? "-" : "", 12400Sstevel@tonic-gate plen - hl, (off & IP_OFFMASK) << 3); 12410Sstevel@tonic-gate } 12420Sstevel@tonic-gate t += strlen(t); 12430Sstevel@tonic-gate 12440Sstevel@tonic-gate if (ipf->fl_flags & FR_KEEPSTATE) { 12450Sstevel@tonic-gate (void) strcpy(t, " K-S"); 12460Sstevel@tonic-gate t += strlen(t); 12470Sstevel@tonic-gate } 12480Sstevel@tonic-gate 12490Sstevel@tonic-gate if (ipf->fl_flags & FR_KEEPFRAG) { 12500Sstevel@tonic-gate (void) strcpy(t, " K-F"); 12510Sstevel@tonic-gate t += strlen(t); 12520Sstevel@tonic-gate } 12530Sstevel@tonic-gate 12540Sstevel@tonic-gate if (ipf->fl_dir == 0) 12550Sstevel@tonic-gate strcpy(t, " IN"); 12560Sstevel@tonic-gate else if (ipf->fl_dir == 1) 12570Sstevel@tonic-gate strcpy(t, " OUT"); 12580Sstevel@tonic-gate t += strlen(t); 12590Sstevel@tonic-gate if (ipf->fl_tag) { 12600Sstevel@tonic-gate sprintf(t, " tag %d", ipf->fl_tag); 12610Sstevel@tonic-gate t += strlen(t); 12620Sstevel@tonic-gate } 12630Sstevel@tonic-gate printipflog: 12640Sstevel@tonic-gate *t++ = '\n'; 12650Sstevel@tonic-gate *t++ = '\0'; 12660Sstevel@tonic-gate if (opts & OPT_SYSLOG) 12670Sstevel@tonic-gate syslog(lvl, "%s", line); 12680Sstevel@tonic-gate else 12690Sstevel@tonic-gate (void) fprintf(log, "%s", line); 12700Sstevel@tonic-gate if (opts & OPT_HEXHDR) 12710Sstevel@tonic-gate dumphex(log, opts, buf, sizeof(iplog_t) + sizeof(*ipf)); 12720Sstevel@tonic-gate if (opts & OPT_HEXBODY) 12730Sstevel@tonic-gate dumphex(log, opts, (char *)ip, ipf->fl_plen + ipf->fl_hlen); 12740Sstevel@tonic-gate else if ((opts & OPT_LOGBODY) && (ipf->fl_flags & FR_LOGBODY)) 12750Sstevel@tonic-gate dumphex(log, opts, (char *)ip + ipf->fl_hlen, ipf->fl_plen); 12760Sstevel@tonic-gate if (conf_file) 12770Sstevel@tonic-gate check_action(buf, opts, line); 12780Sstevel@tonic-gate } 12790Sstevel@tonic-gate 12800Sstevel@tonic-gate 12810Sstevel@tonic-gate static void usage(prog) 12820Sstevel@tonic-gate char *prog; 12830Sstevel@tonic-gate { 12840Sstevel@tonic-gate fprintf(stderr, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s\n", 12850Sstevel@tonic-gate prog, "[-N device]", "[ [-o [NSI]] [-O [NSI]]", 12860Sstevel@tonic-gate "[-P pidfile]", "[-S device]", "[-f device]", 12870Sstevel@tonic-gate "filename"); 12880Sstevel@tonic-gate exit(1); 12890Sstevel@tonic-gate } 12900Sstevel@tonic-gate 12910Sstevel@tonic-gate 12920Sstevel@tonic-gate static void write_pid(file) 12930Sstevel@tonic-gate char *file; 12940Sstevel@tonic-gate { 12950Sstevel@tonic-gate FILE *fp = NULL; 12960Sstevel@tonic-gate int fd; 12970Sstevel@tonic-gate 12980Sstevel@tonic-gate if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 12990Sstevel@tonic-gate fp = fdopen(fd, "w"); 13000Sstevel@tonic-gate if (fp == NULL) { 13010Sstevel@tonic-gate close(fd); 13020Sstevel@tonic-gate fprintf(stderr, 13030Sstevel@tonic-gate "unable to open/create pid file: %s\n", file); 13040Sstevel@tonic-gate return; 13050Sstevel@tonic-gate } 13060Sstevel@tonic-gate fprintf(fp, "%d", getpid()); 13070Sstevel@tonic-gate fclose(fp); 13080Sstevel@tonic-gate } 13090Sstevel@tonic-gate } 13100Sstevel@tonic-gate 13110Sstevel@tonic-gate 13120Sstevel@tonic-gate static void flushlogs(file, log) 13130Sstevel@tonic-gate char *file; 13140Sstevel@tonic-gate FILE *log; 13150Sstevel@tonic-gate { 13160Sstevel@tonic-gate int fd, flushed = 0; 13170Sstevel@tonic-gate 13180Sstevel@tonic-gate if ((fd = open(file, O_RDWR)) == -1) { 13190Sstevel@tonic-gate (void) fprintf(stderr, "%s: open: %s\n", 13200Sstevel@tonic-gate file, STRERROR(errno)); 13210Sstevel@tonic-gate exit(1); 13220Sstevel@tonic-gate } 13230Sstevel@tonic-gate 13240Sstevel@tonic-gate if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 13250Sstevel@tonic-gate printf("%d bytes flushed from log buffer\n", 13260Sstevel@tonic-gate flushed); 13270Sstevel@tonic-gate fflush(stdout); 13280Sstevel@tonic-gate } else 13290Sstevel@tonic-gate perror("SIOCIPFFB"); 13300Sstevel@tonic-gate (void) close(fd); 13310Sstevel@tonic-gate 13320Sstevel@tonic-gate if (flushed) { 13330Sstevel@tonic-gate if (opts & OPT_SYSLOG) 13340Sstevel@tonic-gate syslog(LOG_INFO, "%d bytes flushed from log\n", 13350Sstevel@tonic-gate flushed); 13360Sstevel@tonic-gate else if (log != stdout) 13370Sstevel@tonic-gate fprintf(log, "%d bytes flushed from log\n", flushed); 13380Sstevel@tonic-gate } 13390Sstevel@tonic-gate } 13400Sstevel@tonic-gate 13410Sstevel@tonic-gate 13420Sstevel@tonic-gate static void logopts(turnon, options) 13430Sstevel@tonic-gate int turnon; 13440Sstevel@tonic-gate char *options; 13450Sstevel@tonic-gate { 13460Sstevel@tonic-gate int flags = 0; 13470Sstevel@tonic-gate char *s; 13480Sstevel@tonic-gate 13490Sstevel@tonic-gate for (s = options; *s; s++) 13500Sstevel@tonic-gate { 13510Sstevel@tonic-gate switch (*s) 13520Sstevel@tonic-gate { 13530Sstevel@tonic-gate case 'N' : 13540Sstevel@tonic-gate flags |= OPT_NAT; 13550Sstevel@tonic-gate break; 13560Sstevel@tonic-gate case 'S' : 13570Sstevel@tonic-gate flags |= OPT_STATE; 13580Sstevel@tonic-gate break; 13590Sstevel@tonic-gate case 'I' : 13600Sstevel@tonic-gate flags |= OPT_FILTER; 13610Sstevel@tonic-gate break; 13620Sstevel@tonic-gate default : 13630Sstevel@tonic-gate fprintf(stderr, "Unknown log option %c\n", *s); 13640Sstevel@tonic-gate exit(1); 13650Sstevel@tonic-gate } 13660Sstevel@tonic-gate } 13670Sstevel@tonic-gate 13680Sstevel@tonic-gate if (turnon) 13690Sstevel@tonic-gate opts |= flags; 13700Sstevel@tonic-gate else 13710Sstevel@tonic-gate opts &= ~(flags); 13720Sstevel@tonic-gate } 13730Sstevel@tonic-gate 13740Sstevel@tonic-gate 13750Sstevel@tonic-gate int main(argc, argv) 13760Sstevel@tonic-gate int argc; 13770Sstevel@tonic-gate char *argv[]; 13780Sstevel@tonic-gate { 13790Sstevel@tonic-gate struct stat sb; 13800Sstevel@tonic-gate FILE *log = stdout; 13810Sstevel@tonic-gate int fd[3], doread, n, i; 13820Sstevel@tonic-gate int tr, nr, regular[3], c; 13830Sstevel@tonic-gate int fdt[3], devices = 0, make_daemon = 0; 13840Sstevel@tonic-gate char buf[DEFAULT_IPFLOGSIZE], *iplfile[3], *s; 13850Sstevel@tonic-gate extern int optind; 13860Sstevel@tonic-gate extern char *optarg; 13870Sstevel@tonic-gate 13880Sstevel@tonic-gate fd[0] = fd[1] = fd[2] = -1; 13890Sstevel@tonic-gate fdt[0] = fdt[1] = fdt[2] = -1; 13900Sstevel@tonic-gate iplfile[0] = IPL_NAME; 13910Sstevel@tonic-gate iplfile[1] = IPNAT_NAME; 13920Sstevel@tonic-gate iplfile[2] = IPSTATE_NAME; 13930Sstevel@tonic-gate 13940Sstevel@tonic-gate while ((c = getopt(argc, argv, "?abB:C:Df:FhnN:o:O:pP:sS:tvxX")) != -1) 13950Sstevel@tonic-gate switch (c) 13960Sstevel@tonic-gate { 13970Sstevel@tonic-gate case 'a' : 13980Sstevel@tonic-gate opts |= OPT_LOGALL; 13990Sstevel@tonic-gate fdt[0] = IPL_LOGIPF; 14000Sstevel@tonic-gate fdt[1] = IPL_LOGNAT; 14010Sstevel@tonic-gate fdt[2] = IPL_LOGSTATE; 14020Sstevel@tonic-gate break; 14030Sstevel@tonic-gate case 'b' : 14040Sstevel@tonic-gate opts |= OPT_LOGBODY; 14050Sstevel@tonic-gate break; 14060Sstevel@tonic-gate case 'B' : 14070Sstevel@tonic-gate binarylogfile = optarg; 14080Sstevel@tonic-gate binarylog = fopen(optarg, "a"); 14090Sstevel@tonic-gate break; 14100Sstevel@tonic-gate case 'C' : 14110Sstevel@tonic-gate conf_file = optarg; 14120Sstevel@tonic-gate break; 14130Sstevel@tonic-gate case 'D' : 14140Sstevel@tonic-gate make_daemon = 1; 14150Sstevel@tonic-gate break; 14160Sstevel@tonic-gate case 'f' : case 'I' : 14170Sstevel@tonic-gate opts |= OPT_FILTER; 14180Sstevel@tonic-gate fdt[0] = IPL_LOGIPF; 14190Sstevel@tonic-gate iplfile[0] = optarg; 14200Sstevel@tonic-gate break; 14210Sstevel@tonic-gate case 'F' : 14220Sstevel@tonic-gate flushlogs(iplfile[0], log); 14230Sstevel@tonic-gate flushlogs(iplfile[1], log); 14240Sstevel@tonic-gate flushlogs(iplfile[2], log); 14250Sstevel@tonic-gate break; 14260Sstevel@tonic-gate case 'n' : 14270Sstevel@tonic-gate opts |= OPT_RESOLVE; 14280Sstevel@tonic-gate break; 14290Sstevel@tonic-gate case 'N' : 14300Sstevel@tonic-gate opts |= OPT_NAT; 14310Sstevel@tonic-gate fdt[1] = IPL_LOGNAT; 14320Sstevel@tonic-gate iplfile[1] = optarg; 14330Sstevel@tonic-gate break; 14340Sstevel@tonic-gate case 'o' : case 'O' : 14350Sstevel@tonic-gate logopts(c == 'o', optarg); 14360Sstevel@tonic-gate fdt[0] = fdt[1] = fdt[2] = -1; 14370Sstevel@tonic-gate if (opts & OPT_FILTER) 14380Sstevel@tonic-gate fdt[0] = IPL_LOGIPF; 14390Sstevel@tonic-gate if (opts & OPT_NAT) 14400Sstevel@tonic-gate fdt[1] = IPL_LOGNAT; 14410Sstevel@tonic-gate if (opts & OPT_STATE) 14420Sstevel@tonic-gate fdt[2] = IPL_LOGSTATE; 14430Sstevel@tonic-gate break; 14440Sstevel@tonic-gate case 'p' : 14450Sstevel@tonic-gate opts |= OPT_PORTNUM; 14460Sstevel@tonic-gate break; 14470Sstevel@tonic-gate case 'P' : 14480Sstevel@tonic-gate pidfile = optarg; 14490Sstevel@tonic-gate break; 14500Sstevel@tonic-gate case 's' : 14510Sstevel@tonic-gate s = strrchr(argv[0], '/'); 14520Sstevel@tonic-gate if (s == NULL) 14530Sstevel@tonic-gate s = argv[0]; 14540Sstevel@tonic-gate else 14550Sstevel@tonic-gate s++; 14560Sstevel@tonic-gate openlog(s, LOG_NDELAY|LOG_PID, LOGFAC); 14570Sstevel@tonic-gate s = NULL; 14580Sstevel@tonic-gate opts |= OPT_SYSLOG; 14590Sstevel@tonic-gate log = NULL; 14600Sstevel@tonic-gate break; 14610Sstevel@tonic-gate case 'S' : 14620Sstevel@tonic-gate opts |= OPT_STATE; 14630Sstevel@tonic-gate fdt[2] = IPL_LOGSTATE; 14640Sstevel@tonic-gate iplfile[2] = optarg; 14650Sstevel@tonic-gate break; 14660Sstevel@tonic-gate case 't' : 14670Sstevel@tonic-gate opts |= OPT_TAIL; 14680Sstevel@tonic-gate break; 14690Sstevel@tonic-gate case 'v' : 14700Sstevel@tonic-gate opts |= OPT_VERBOSE; 14710Sstevel@tonic-gate break; 14720Sstevel@tonic-gate case 'x' : 14730Sstevel@tonic-gate opts |= OPT_HEXBODY; 14740Sstevel@tonic-gate break; 14750Sstevel@tonic-gate case 'X' : 14760Sstevel@tonic-gate opts |= OPT_HEXHDR; 14770Sstevel@tonic-gate break; 14780Sstevel@tonic-gate default : 14790Sstevel@tonic-gate case 'h' : 14800Sstevel@tonic-gate case '?' : 14810Sstevel@tonic-gate usage(argv[0]); 14820Sstevel@tonic-gate } 14830Sstevel@tonic-gate 14840Sstevel@tonic-gate init_tabs(); 14850Sstevel@tonic-gate if (conf_file) 14860Sstevel@tonic-gate if (load_config(conf_file) == -1) 14870Sstevel@tonic-gate exit(1); 14880Sstevel@tonic-gate 14890Sstevel@tonic-gate /* 14900Sstevel@tonic-gate * Default action is to only open the filter log file. 14910Sstevel@tonic-gate */ 14920Sstevel@tonic-gate if ((fdt[0] == -1) && (fdt[1] == -1) && (fdt[2] == -1)) 14930Sstevel@tonic-gate fdt[0] = IPL_LOGIPF; 14940Sstevel@tonic-gate 14950Sstevel@tonic-gate for (i = 0; i < 3; i++) { 14960Sstevel@tonic-gate if (fdt[i] == -1) 14970Sstevel@tonic-gate continue; 14980Sstevel@tonic-gate if (!strcmp(iplfile[i], "-")) 14990Sstevel@tonic-gate fd[i] = 0; 15000Sstevel@tonic-gate else { 15010Sstevel@tonic-gate if ((fd[i] = open(iplfile[i], O_RDONLY)) == -1) { 15020Sstevel@tonic-gate (void) fprintf(stderr, 15030Sstevel@tonic-gate "%s: open: %s\n", iplfile[i], 15040Sstevel@tonic-gate STRERROR(errno)); 15050Sstevel@tonic-gate exit(1); 15060Sstevel@tonic-gate /* NOTREACHED */ 15070Sstevel@tonic-gate } 15080Sstevel@tonic-gate if (fstat(fd[i], &sb) == -1) { 15090Sstevel@tonic-gate (void) fprintf(stderr, "%d: fstat: %s\n", 15100Sstevel@tonic-gate fd[i], STRERROR(errno)); 15110Sstevel@tonic-gate exit(1); 15120Sstevel@tonic-gate /* NOTREACHED */ 15130Sstevel@tonic-gate } 15140Sstevel@tonic-gate if (!(regular[i] = !S_ISCHR(sb.st_mode))) 15150Sstevel@tonic-gate devices++; 15160Sstevel@tonic-gate } 15170Sstevel@tonic-gate } 15180Sstevel@tonic-gate 15190Sstevel@tonic-gate if (!(opts & OPT_SYSLOG)) { 15200Sstevel@tonic-gate logfile = argv[optind]; 15210Sstevel@tonic-gate log = logfile ? fopen(logfile, "a") : stdout; 15220Sstevel@tonic-gate if (log == NULL) { 15230Sstevel@tonic-gate (void) fprintf(stderr, "%s: fopen: %s\n", 15240Sstevel@tonic-gate argv[optind], STRERROR(errno)); 15250Sstevel@tonic-gate exit(1); 15260Sstevel@tonic-gate /* NOTREACHED */ 15270Sstevel@tonic-gate } 15280Sstevel@tonic-gate setvbuf(log, NULL, _IONBF, 0); 15290Sstevel@tonic-gate } else 15300Sstevel@tonic-gate log = NULL; 15310Sstevel@tonic-gate 15320Sstevel@tonic-gate if (make_daemon && ((log != stdout) || (opts & OPT_SYSLOG))) { 15330Sstevel@tonic-gate #if BSD >= 199306 15340Sstevel@tonic-gate daemon(0, !(opts & OPT_SYSLOG)); 15350Sstevel@tonic-gate #else 15360Sstevel@tonic-gate int pid; 15370Sstevel@tonic-gate if ((pid = fork()) > 0) 15380Sstevel@tonic-gate exit(0); 15390Sstevel@tonic-gate if (pid < 0) { 15400Sstevel@tonic-gate (void) fprintf(stderr, "%s: fork() failed: %s\n", 15410Sstevel@tonic-gate argv[0], STRERROR(errno)); 15420Sstevel@tonic-gate exit(1); 15430Sstevel@tonic-gate /* NOTREACHED */ 15440Sstevel@tonic-gate } 15450Sstevel@tonic-gate setsid(); 15460Sstevel@tonic-gate if ((opts & OPT_SYSLOG)) 15470Sstevel@tonic-gate close(2); 15480Sstevel@tonic-gate #endif /* !BSD */ 15490Sstevel@tonic-gate close(0); 15500Sstevel@tonic-gate close(1); 15510Sstevel@tonic-gate } 15520Sstevel@tonic-gate write_pid(pidfile); 15530Sstevel@tonic-gate 15540Sstevel@tonic-gate signal(SIGHUP, handlehup); 15550Sstevel@tonic-gate 15560Sstevel@tonic-gate for (doread = 1; doread; ) { 15570Sstevel@tonic-gate nr = 0; 15580Sstevel@tonic-gate 15590Sstevel@tonic-gate for (i = 0; i < 3; i++) { 15600Sstevel@tonic-gate tr = 0; 15610Sstevel@tonic-gate if (fdt[i] == -1) 15620Sstevel@tonic-gate continue; 15630Sstevel@tonic-gate if (!regular[i]) { 15640Sstevel@tonic-gate if (ioctl(fd[i], FIONREAD, &tr) == -1) { 15650Sstevel@tonic-gate if (opts & OPT_SYSLOG) 15660Sstevel@tonic-gate syslog(LOG_CRIT, 15670Sstevel@tonic-gate "ioctl(FIONREAD): %m"); 15680Sstevel@tonic-gate else 15690Sstevel@tonic-gate perror("ioctl(FIONREAD)"); 15700Sstevel@tonic-gate exit(1); 15710Sstevel@tonic-gate /* NOTREACHED */ 15720Sstevel@tonic-gate } 15730Sstevel@tonic-gate } else { 15740Sstevel@tonic-gate tr = (lseek(fd[i], 0, SEEK_CUR) < sb.st_size); 15750Sstevel@tonic-gate if (!tr && !(opts & OPT_TAIL)) 15760Sstevel@tonic-gate doread = 0; 15770Sstevel@tonic-gate } 15780Sstevel@tonic-gate if (!tr) 15790Sstevel@tonic-gate continue; 15800Sstevel@tonic-gate nr += tr; 15810Sstevel@tonic-gate 15820Sstevel@tonic-gate tr = read_log(fd[i], &n, buf, sizeof(buf)); 15830Sstevel@tonic-gate if (donehup) { 15840Sstevel@tonic-gate donehup = 0; 15850Sstevel@tonic-gate if (newlog) { 15860Sstevel@tonic-gate fclose(log); 15870Sstevel@tonic-gate log = newlog; 15880Sstevel@tonic-gate newlog = NULL; 15890Sstevel@tonic-gate } 15900Sstevel@tonic-gate if (newbinarylog) { 15910Sstevel@tonic-gate fclose(binarylog); 15920Sstevel@tonic-gate binarylog = newbinarylog; 15930Sstevel@tonic-gate newbinarylog = NULL; 15940Sstevel@tonic-gate } 15950Sstevel@tonic-gate } 15960Sstevel@tonic-gate 15970Sstevel@tonic-gate switch (tr) 15980Sstevel@tonic-gate { 15990Sstevel@tonic-gate case -1 : 16000Sstevel@tonic-gate if (opts & OPT_SYSLOG) 16010Sstevel@tonic-gate syslog(LOG_CRIT, "read: %m\n"); 16020Sstevel@tonic-gate else 16030Sstevel@tonic-gate perror("read"); 16040Sstevel@tonic-gate doread = 0; 16050Sstevel@tonic-gate break; 16060Sstevel@tonic-gate case 1 : 16070Sstevel@tonic-gate if (opts & OPT_SYSLOG) 16080Sstevel@tonic-gate syslog(LOG_CRIT, "aborting logging\n"); 16090Sstevel@tonic-gate else 16100Sstevel@tonic-gate fprintf(log, "aborting logging\n"); 16110Sstevel@tonic-gate doread = 0; 16120Sstevel@tonic-gate break; 16130Sstevel@tonic-gate case 2 : 16140Sstevel@tonic-gate break; 16150Sstevel@tonic-gate case 0 : 16160Sstevel@tonic-gate if (n > 0) { 16170Sstevel@tonic-gate print_log(fdt[i], log, buf, n); 16180Sstevel@tonic-gate if (!(opts & OPT_SYSLOG)) 16190Sstevel@tonic-gate fflush(log); 16200Sstevel@tonic-gate } 16210Sstevel@tonic-gate break; 16220Sstevel@tonic-gate } 16230Sstevel@tonic-gate } 16240Sstevel@tonic-gate if (!nr && ((opts & OPT_TAIL) || devices)) 16250Sstevel@tonic-gate sleep(1); 16260Sstevel@tonic-gate } 16270Sstevel@tonic-gate return(0); 16280Sstevel@tonic-gate /* NOTREACHED */ 16290Sstevel@tonic-gate } 1630