141edb306SCy Schubert /* $FreeBSD$ */ 241edb306SCy Schubert 341edb306SCy Schubert /* 441edb306SCy Schubert * Copyright (C) 2012 by Darren Reed. 541edb306SCy Schubert * 641edb306SCy Schubert * See the IPFILTER.LICENCE file for details on licencing. 741edb306SCy Schubert */ 841edb306SCy Schubert #include "ipf.h" 941edb306SCy Schubert #include "ipmon.h" 1041edb306SCy Schubert #include <sys/ioctl.h> 1141edb306SCy Schubert #include <sys/stat.h> 1241edb306SCy Schubert #include <syslog.h> 1341edb306SCy Schubert #include <ctype.h> 1441edb306SCy Schubert #include <fcntl.h> 1541edb306SCy Schubert #include <signal.h> 1641edb306SCy Schubert 1741edb306SCy Schubert #if !defined(lint) 1841edb306SCy Schubert static const char sccsid[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed"; 1941edb306SCy Schubert static const char rcsid[] = "@(#)$Id$"; 2041edb306SCy Schubert #endif 2141edb306SCy Schubert 2241edb306SCy Schubert 2341edb306SCy Schubert #define STRERROR(x) strerror(x) 2441edb306SCy Schubert 2541edb306SCy Schubert extern int optind; 2641edb306SCy Schubert extern char *optarg; 2741edb306SCy Schubert 2841edb306SCy Schubert extern ipmon_saver_t executesaver; 2941edb306SCy Schubert extern ipmon_saver_t filesaver; 3041edb306SCy Schubert extern ipmon_saver_t nothingsaver; 3141edb306SCy Schubert extern ipmon_saver_t snmpv1saver; 3241edb306SCy Schubert extern ipmon_saver_t snmpv2saver; 3341edb306SCy Schubert extern ipmon_saver_t syslogsaver; 3441edb306SCy Schubert 3541edb306SCy Schubert 3641edb306SCy Schubert struct flags { 3741edb306SCy Schubert int value; 3841edb306SCy Schubert char flag; 3941edb306SCy Schubert }; 4041edb306SCy Schubert 4141edb306SCy Schubert typedef struct logsource { 4241edb306SCy Schubert int fd; 4341edb306SCy Schubert int logtype; 4441edb306SCy Schubert char *file; 4541edb306SCy Schubert int regular; 4641edb306SCy Schubert size_t size; 4741edb306SCy Schubert } logsource_t; 4841edb306SCy Schubert 4941edb306SCy Schubert typedef struct config { 5041edb306SCy Schubert int opts; 5141edb306SCy Schubert int maxfd; 5241edb306SCy Schubert logsource_t logsrc[3]; 5341edb306SCy Schubert fd_set fdmr; 5441edb306SCy Schubert FILE *blog; 5541edb306SCy Schubert char *bfile; 5641edb306SCy Schubert FILE *log; 5741edb306SCy Schubert char *file; 5841edb306SCy Schubert char *cfile; 5941edb306SCy Schubert } config_t; 6041edb306SCy Schubert 6141edb306SCy Schubert typedef struct icmp_subtype { 6241edb306SCy Schubert int ist_val; 6341edb306SCy Schubert char *ist_name; 6441edb306SCy Schubert } icmp_subtype_t; 6541edb306SCy Schubert 6641edb306SCy Schubert typedef struct icmp_type { 6741edb306SCy Schubert int it_val; 6841edb306SCy Schubert struct icmp_subtype *it_subtable; 6941edb306SCy Schubert size_t it_stsize; 7041edb306SCy Schubert char *it_name; 7141edb306SCy Schubert } icmp_type_t; 7241edb306SCy Schubert 7341edb306SCy Schubert 7441edb306SCy Schubert #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t)) 7541edb306SCy Schubert 7641edb306SCy Schubert 7741edb306SCy Schubert struct flags tcpfl[] = { 7841edb306SCy Schubert { TH_ACK, 'A' }, 7941edb306SCy Schubert { TH_RST, 'R' }, 8041edb306SCy Schubert { TH_SYN, 'S' }, 8141edb306SCy Schubert { TH_FIN, 'F' }, 8241edb306SCy Schubert { TH_URG, 'U' }, 8341edb306SCy Schubert { TH_PUSH,'P' }, 8441edb306SCy Schubert { TH_ECN, 'E' }, 8541edb306SCy Schubert { TH_CWR, 'C' }, 8641edb306SCy Schubert { 0, '\0' } 8741edb306SCy Schubert }; 8841edb306SCy Schubert 8941edb306SCy Schubert char *reasons[] = { 9041edb306SCy Schubert "filter-rule", 9141edb306SCy Schubert "log-or-block_1", 9241edb306SCy Schubert "pps-rate", 9341edb306SCy Schubert "jumbogram", 9441edb306SCy Schubert "makefrip-fail", 9541edb306SCy Schubert "state_add-fail", 9641edb306SCy Schubert "updateipid-fail", 9741edb306SCy Schubert "log-or-block_2", 9841edb306SCy Schubert "decap-fail", 9941edb306SCy Schubert "auth_new-fail", 10041edb306SCy Schubert "auth_captured", 10141edb306SCy Schubert "coalesce-fail", 10241edb306SCy Schubert "pullup-fail", 10341edb306SCy Schubert "auth-feedback", 10441edb306SCy Schubert "bad-frag", 10541edb306SCy Schubert "natv4_out-fail", 10641edb306SCy Schubert "natv4_in-fail", 10741edb306SCy Schubert "natv6_out-fail", 10841edb306SCy Schubert "natv6_in-fail", 10941edb306SCy Schubert }; 11041edb306SCy Schubert 11141edb306SCy Schubert #if SOLARIS 11241edb306SCy Schubert static char *pidfile = "/etc/opt/ipf/ipmon.pid"; 11341edb306SCy Schubert #else 11441edb306SCy Schubert static char *pidfile = "/var/run/ipmon.pid"; 11541edb306SCy Schubert #endif 11641edb306SCy Schubert 11741edb306SCy Schubert static char line[2048]; 11841edb306SCy Schubert static int donehup = 0; 11941edb306SCy Schubert static void usage(char *); 12041edb306SCy Schubert static void handlehup(int); 12141edb306SCy Schubert static void flushlogs(char *, FILE *); 12241edb306SCy Schubert static void print_log(config_t *, logsource_t *, char *, int); 12341edb306SCy Schubert static void print_ipflog(config_t *, char *, int); 12441edb306SCy Schubert static void print_natlog(config_t *, char *, int); 12541edb306SCy Schubert static void print_statelog(config_t *, char *, int); 12641edb306SCy Schubert static int read_log(int, int *, char *, int); 12741edb306SCy Schubert static void write_pid(char *); 12841edb306SCy Schubert static char *icmpname(u_int, u_int); 12941edb306SCy Schubert static char *icmpname6(u_int, u_int); 13041edb306SCy Schubert static icmp_type_t *find_icmptype(int, icmp_type_t *, size_t); 13141edb306SCy Schubert static icmp_subtype_t *find_icmpsubtype(int, icmp_subtype_t *, size_t); 13241edb306SCy Schubert static struct tm *get_tm(time_t); 13341edb306SCy Schubert 13441edb306SCy Schubert char *portlocalname(int, char *, u_int); 13541edb306SCy Schubert int main(int, char *[]); 13641edb306SCy Schubert 13741edb306SCy Schubert static void logopts(int, char *); 13841edb306SCy Schubert static void init_tabs(void); 13941edb306SCy Schubert static char *getlocalproto(u_int); 14041edb306SCy Schubert static void openlogs(config_t *conf); 14141edb306SCy Schubert static int read_loginfo(config_t *conf); 14241edb306SCy Schubert static void initconfig(config_t *conf); 14341edb306SCy Schubert 14441edb306SCy Schubert static char **protocols = NULL; 14541edb306SCy Schubert static char **udp_ports = NULL; 14641edb306SCy Schubert static char **tcp_ports = NULL; 14741edb306SCy Schubert 14841edb306SCy Schubert 14941edb306SCy Schubert #define HOSTNAMEV4(b) hostname(AF_INET, (u_32_t *)&(b)) 15041edb306SCy Schubert 15141edb306SCy Schubert #ifndef LOGFAC 15241edb306SCy Schubert #define LOGFAC LOG_LOCAL0 15341edb306SCy Schubert #endif 15441edb306SCy Schubert int logfac = LOGFAC; 15541edb306SCy Schubert int ipmonopts = 0; 15641edb306SCy Schubert int opts = OPT_NORESOLVE; 15741edb306SCy Schubert int use_inet6 = 0; 15841edb306SCy Schubert 15941edb306SCy Schubert 16041edb306SCy Schubert static icmp_subtype_t icmpunreachnames[] = { 16141edb306SCy Schubert { ICMP_UNREACH_NET, "net" }, 16241edb306SCy Schubert { ICMP_UNREACH_HOST, "host" }, 16341edb306SCy Schubert { ICMP_UNREACH_PROTOCOL, "protocol" }, 16441edb306SCy Schubert { ICMP_UNREACH_PORT, "port" }, 16541edb306SCy Schubert { ICMP_UNREACH_NEEDFRAG, "needfrag" }, 16641edb306SCy Schubert { ICMP_UNREACH_SRCFAIL, "srcfail" }, 16741edb306SCy Schubert { ICMP_UNREACH_NET_UNKNOWN, "net_unknown" }, 16841edb306SCy Schubert { ICMP_UNREACH_HOST_UNKNOWN, "host_unknown" }, 16941edb306SCy Schubert { ICMP_UNREACH_NET, "isolated" }, 17041edb306SCy Schubert { ICMP_UNREACH_NET_PROHIB, "net_prohib" }, 17141edb306SCy Schubert { ICMP_UNREACH_NET_PROHIB, "host_prohib" }, 17241edb306SCy Schubert { ICMP_UNREACH_TOSNET, "tosnet" }, 17341edb306SCy Schubert { ICMP_UNREACH_TOSHOST, "toshost" }, 17441edb306SCy Schubert { ICMP_UNREACH_ADMIN_PROHIBIT, "admin_prohibit" }, 17541edb306SCy Schubert { -2, NULL } 17641edb306SCy Schubert }; 17741edb306SCy Schubert 17841edb306SCy Schubert static icmp_subtype_t redirectnames[] = { 17941edb306SCy Schubert { ICMP_REDIRECT_NET, "net" }, 18041edb306SCy Schubert { ICMP_REDIRECT_HOST, "host" }, 18141edb306SCy Schubert { ICMP_REDIRECT_TOSNET, "tosnet" }, 18241edb306SCy Schubert { ICMP_REDIRECT_TOSHOST, "toshost" }, 18341edb306SCy Schubert { -2, NULL } 18441edb306SCy Schubert }; 18541edb306SCy Schubert 18641edb306SCy Schubert static icmp_subtype_t timxceednames[] = { 18741edb306SCy Schubert { ICMP_TIMXCEED_INTRANS, "transit" }, 18841edb306SCy Schubert { ICMP_TIMXCEED_REASS, "reassem" }, 18941edb306SCy Schubert { -2, NULL } 19041edb306SCy Schubert }; 19141edb306SCy Schubert 19241edb306SCy Schubert static icmp_subtype_t paramnames[] = { 19341edb306SCy Schubert { ICMP_PARAMPROB_ERRATPTR, "errata_pointer" }, 19441edb306SCy Schubert { ICMP_PARAMPROB_OPTABSENT, "optmissing" }, 19541edb306SCy Schubert { ICMP_PARAMPROB_LENGTH, "length" }, 19641edb306SCy Schubert { -2, NULL } 19741edb306SCy Schubert }; 19841edb306SCy Schubert 19941edb306SCy Schubert static icmp_type_t icmptypes4[] = { 20041edb306SCy Schubert { ICMP_ECHOREPLY, NULL, 0, "echoreply" }, 20141edb306SCy Schubert { -1, NULL, 0, NULL }, 20241edb306SCy Schubert { -1, NULL, 0, NULL }, 20341edb306SCy Schubert { ICMP_UNREACH, icmpunreachnames, 20441edb306SCy Schubert IST_SZ(icmpunreachnames),"unreach" }, 20541edb306SCy Schubert { ICMP_SOURCEQUENCH, NULL, 0, "sourcequench" }, 20641edb306SCy Schubert { ICMP_REDIRECT, redirectnames, 20741edb306SCy Schubert IST_SZ(redirectnames), "redirect" }, 20841edb306SCy Schubert { -1, NULL, 0, NULL }, 20941edb306SCy Schubert { -1, NULL, 0, NULL }, 21041edb306SCy Schubert { ICMP_ECHO, NULL, 0, "echo" }, 21141edb306SCy Schubert { ICMP_ROUTERADVERT, NULL, 0, "routeradvert" }, 21241edb306SCy Schubert { ICMP_ROUTERSOLICIT, NULL, 0, "routersolicit" }, 21341edb306SCy Schubert { ICMP_TIMXCEED, timxceednames, 21441edb306SCy Schubert IST_SZ(timxceednames), "timxceed" }, 21541edb306SCy Schubert { ICMP_PARAMPROB, paramnames, 21641edb306SCy Schubert IST_SZ(paramnames), "paramprob" }, 21741edb306SCy Schubert { ICMP_TSTAMP, NULL, 0, "timestamp" }, 21841edb306SCy Schubert { ICMP_TSTAMPREPLY, NULL, 0, "timestampreply" }, 21941edb306SCy Schubert { ICMP_IREQ, NULL, 0, "inforeq" }, 22041edb306SCy Schubert { ICMP_IREQREPLY, NULL, 0, "inforeply" }, 22141edb306SCy Schubert { ICMP_MASKREQ, NULL, 0, "maskreq" }, 22241edb306SCy Schubert { ICMP_MASKREPLY, NULL, 0, "maskreply" }, 22341edb306SCy Schubert { -2, NULL, 0, NULL } 22441edb306SCy Schubert }; 22541edb306SCy Schubert 22641edb306SCy Schubert static icmp_subtype_t icmpredirect6[] = { 22741edb306SCy Schubert { ICMP6_DST_UNREACH_NOROUTE, "noroute" }, 22841edb306SCy Schubert { ICMP6_DST_UNREACH_ADMIN, "admin" }, 22941edb306SCy Schubert { ICMP6_DST_UNREACH_NOTNEIGHBOR, "neighbour" }, 23041edb306SCy Schubert { ICMP6_DST_UNREACH_ADDR, "address" }, 23141edb306SCy Schubert { ICMP6_DST_UNREACH_NOPORT, "noport" }, 23241edb306SCy Schubert { -2, NULL } 23341edb306SCy Schubert }; 23441edb306SCy Schubert 23541edb306SCy Schubert static icmp_subtype_t icmptimexceed6[] = { 23641edb306SCy Schubert { ICMP6_TIME_EXCEED_TRANSIT, "intransit" }, 23741edb306SCy Schubert { ICMP6_TIME_EXCEED_REASSEMBLY, "reassem" }, 23841edb306SCy Schubert { -2, NULL } 23941edb306SCy Schubert }; 24041edb306SCy Schubert 24141edb306SCy Schubert static icmp_subtype_t icmpparamprob6[] = { 24241edb306SCy Schubert { ICMP6_PARAMPROB_HEADER, "header" }, 24341edb306SCy Schubert { ICMP6_PARAMPROB_NEXTHEADER, "nextheader" }, 24441edb306SCy Schubert { ICMP6_PARAMPROB_OPTION, "option" }, 24541edb306SCy Schubert { -2, NULL } 24641edb306SCy Schubert }; 24741edb306SCy Schubert 24841edb306SCy Schubert static icmp_subtype_t icmpquerysubject6[] = { 24941edb306SCy Schubert { ICMP6_NI_SUBJ_IPV6, "ipv6" }, 25041edb306SCy Schubert { ICMP6_NI_SUBJ_FQDN, "fqdn" }, 25141edb306SCy Schubert { ICMP6_NI_SUBJ_IPV4, "ipv4" }, 25241edb306SCy Schubert { -2, NULL }, 25341edb306SCy Schubert }; 25441edb306SCy Schubert 25541edb306SCy Schubert static icmp_subtype_t icmpnodeinfo6[] = { 25641edb306SCy Schubert { ICMP6_NI_SUCCESS, "success" }, 25741edb306SCy Schubert { ICMP6_NI_REFUSED, "refused" }, 25841edb306SCy Schubert { ICMP6_NI_UNKNOWN, "unknown" }, 25941edb306SCy Schubert { -2, NULL } 26041edb306SCy Schubert }; 26141edb306SCy Schubert 26241edb306SCy Schubert static icmp_subtype_t icmprenumber6[] = { 26341edb306SCy Schubert { ICMP6_ROUTER_RENUMBERING_COMMAND, "command" }, 26441edb306SCy Schubert { ICMP6_ROUTER_RENUMBERING_RESULT, "result" }, 26541edb306SCy Schubert { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET, "seqnum_reset" }, 26641edb306SCy Schubert { -2, NULL } 26741edb306SCy Schubert }; 26841edb306SCy Schubert 26941edb306SCy Schubert static icmp_type_t icmptypes6[] = { 27041edb306SCy Schubert { 0, NULL, 0, NULL }, 27141edb306SCy Schubert { ICMP6_DST_UNREACH, icmpredirect6, 27241edb306SCy Schubert IST_SZ(icmpredirect6), "unreach" }, 27341edb306SCy Schubert { ICMP6_PACKET_TOO_BIG, NULL, 0, "toobig" }, 27441edb306SCy Schubert { ICMP6_TIME_EXCEEDED, icmptimexceed6, 27541edb306SCy Schubert IST_SZ(icmptimexceed6), "timxceed" }, 27641edb306SCy Schubert { ICMP6_PARAM_PROB, icmpparamprob6, 27741edb306SCy Schubert IST_SZ(icmpparamprob6), "paramprob" }, 27841edb306SCy Schubert { ICMP6_ECHO_REQUEST, NULL, 0, "echo" }, 27941edb306SCy Schubert { ICMP6_ECHO_REPLY, NULL, 0, "echoreply" }, 28041edb306SCy Schubert { ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6, 28141edb306SCy Schubert IST_SZ(icmpquerysubject6), "groupmemberquery" }, 28241edb306SCy Schubert { ICMP6_MEMBERSHIP_REPORT,NULL, 0, "groupmemberreport" }, 28341edb306SCy Schubert { ICMP6_MEMBERSHIP_REDUCTION,NULL, 0, "groupmemberterm" }, 28441edb306SCy Schubert { ND_ROUTER_SOLICIT, NULL, 0, "routersolicit" }, 28541edb306SCy Schubert { ND_ROUTER_ADVERT, NULL, 0, "routeradvert" }, 28641edb306SCy Schubert { ND_NEIGHBOR_SOLICIT, NULL, 0, "neighborsolicit" }, 28741edb306SCy Schubert { ND_NEIGHBOR_ADVERT, NULL, 0, "neighboradvert" }, 28841edb306SCy Schubert { ND_REDIRECT, NULL, 0, "redirect" }, 28941edb306SCy Schubert { ICMP6_ROUTER_RENUMBERING, icmprenumber6, 29041edb306SCy Schubert IST_SZ(icmprenumber6), "routerrenumber" }, 29141edb306SCy Schubert { ICMP6_WRUREQUEST, NULL, 0, "whoareyourequest" }, 29241edb306SCy Schubert { ICMP6_WRUREPLY, NULL, 0, "whoareyoureply" }, 29341edb306SCy Schubert { ICMP6_FQDN_QUERY, NULL, 0, "fqdnquery" }, 29441edb306SCy Schubert { ICMP6_FQDN_REPLY, NULL, 0, "fqdnreply" }, 29541edb306SCy Schubert { ICMP6_NI_QUERY, icmpnodeinfo6, 29641edb306SCy Schubert IST_SZ(icmpnodeinfo6), "nodeinforequest" }, 29741edb306SCy Schubert { ICMP6_NI_REPLY, NULL, 0, "nodeinforeply" }, 29841edb306SCy Schubert { MLD6_MTRACE_RESP, NULL, 0, "mtraceresponse" }, 29941edb306SCy Schubert { MLD6_MTRACE, NULL, 0, "mtracerequest" }, 30041edb306SCy Schubert { -2, NULL, 0, NULL } 30141edb306SCy Schubert }; 30241edb306SCy Schubert 303efeb8bffSCy Schubert static icmp_subtype_t * 304efeb8bffSCy Schubert find_icmpsubtype(int type, icmp_subtype_t *table, size_t tablesz) 30541edb306SCy Schubert { 30641edb306SCy Schubert icmp_subtype_t *ist; 30741edb306SCy Schubert int i; 30841edb306SCy Schubert 30941edb306SCy Schubert if (tablesz < 2) 3102582ae57SCy Schubert return (NULL); 31141edb306SCy Schubert 31241edb306SCy Schubert if ((type < 0) || (type > table[tablesz - 2].ist_val)) 3132582ae57SCy Schubert return (NULL); 31441edb306SCy Schubert 31541edb306SCy Schubert i = type; 31641edb306SCy Schubert if (table[type].ist_val == type) 3172582ae57SCy Schubert return (table + type); 31841edb306SCy Schubert 31941edb306SCy Schubert for (i = 0, ist = table; ist->ist_val != -2; i++, ist++) 32041edb306SCy Schubert if (ist->ist_val == type) 3212582ae57SCy Schubert return (ist); 3222582ae57SCy Schubert return (NULL); 32341edb306SCy Schubert } 32441edb306SCy Schubert 32541edb306SCy Schubert 326efeb8bffSCy Schubert static icmp_type_t * 327efeb8bffSCy Schubert find_icmptype(int type, icmp_type_t *table, size_t tablesz) 32841edb306SCy Schubert { 32941edb306SCy Schubert icmp_type_t *it; 33041edb306SCy Schubert int i; 33141edb306SCy Schubert 33241edb306SCy Schubert if (tablesz < 2) 3332582ae57SCy Schubert return (NULL); 33441edb306SCy Schubert 33541edb306SCy Schubert if ((type < 0) || (type > table[tablesz - 2].it_val)) 3362582ae57SCy Schubert return (NULL); 33741edb306SCy Schubert 33841edb306SCy Schubert i = type; 33941edb306SCy Schubert if (table[type].it_val == type) 3402582ae57SCy Schubert return (table + type); 34141edb306SCy Schubert 34241edb306SCy Schubert for (i = 0, it = table; it->it_val != -2; i++, it++) 34341edb306SCy Schubert if (it->it_val == type) 3442582ae57SCy Schubert return (it); 3452582ae57SCy Schubert return (NULL); 34641edb306SCy Schubert } 34741edb306SCy Schubert 34841edb306SCy Schubert 349efeb8bffSCy Schubert static void 350efeb8bffSCy Schubert handlehup(int sig) 35141edb306SCy Schubert { 35241edb306SCy Schubert signal(SIGHUP, handlehup); 35341edb306SCy Schubert donehup = 1; 35441edb306SCy Schubert } 35541edb306SCy Schubert 35641edb306SCy Schubert 357efeb8bffSCy Schubert static void 358efeb8bffSCy Schubert init_tabs(void) 35941edb306SCy Schubert { 36041edb306SCy Schubert struct protoent *p; 36141edb306SCy Schubert struct servent *s; 36241edb306SCy Schubert char *name, **tab; 36341edb306SCy Schubert int port, i; 36441edb306SCy Schubert 36541edb306SCy Schubert if (protocols != NULL) { 36641edb306SCy Schubert for (i = 0; i < 256; i++) 36741edb306SCy Schubert if (protocols[i] != NULL) { 36841edb306SCy Schubert free(protocols[i]); 36941edb306SCy Schubert protocols[i] = NULL; 37041edb306SCy Schubert } 37141edb306SCy Schubert free(protocols); 37241edb306SCy Schubert protocols = NULL; 37341edb306SCy Schubert } 37441edb306SCy Schubert protocols = (char **)malloc(256 * sizeof(*protocols)); 37541edb306SCy Schubert if (protocols != NULL) { 37641edb306SCy Schubert bzero((char *)protocols, 256 * sizeof(*protocols)); 37741edb306SCy Schubert 37841edb306SCy Schubert setprotoent(1); 37941edb306SCy Schubert while ((p = getprotoent()) != NULL) 38041edb306SCy Schubert if (p->p_proto >= 0 && p->p_proto <= 255 && 38141edb306SCy Schubert p->p_name != NULL && protocols[p->p_proto] == NULL) 38241edb306SCy Schubert protocols[p->p_proto] = strdup(p->p_name); 38341edb306SCy Schubert endprotoent(); 38441edb306SCy Schubert if (protocols[0]) 38541edb306SCy Schubert free(protocols[0]); 38641edb306SCy Schubert protocols[0] = strdup("ip"); 38741edb306SCy Schubert } 38841edb306SCy Schubert 38941edb306SCy Schubert if (udp_ports != NULL) { 39041edb306SCy Schubert for (i = 0; i < 65536; i++) 39141edb306SCy Schubert if (udp_ports[i] != NULL) { 39241edb306SCy Schubert free(udp_ports[i]); 39341edb306SCy Schubert udp_ports[i] = NULL; 39441edb306SCy Schubert } 39541edb306SCy Schubert free(udp_ports); 39641edb306SCy Schubert udp_ports = NULL; 39741edb306SCy Schubert } 39841edb306SCy Schubert udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 39941edb306SCy Schubert if (udp_ports != NULL) 40041edb306SCy Schubert bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 40141edb306SCy Schubert 40241edb306SCy Schubert if (tcp_ports != NULL) { 40341edb306SCy Schubert for (i = 0; i < 65536; i++) 40441edb306SCy Schubert if (tcp_ports[i] != NULL) { 40541edb306SCy Schubert free(tcp_ports[i]); 40641edb306SCy Schubert tcp_ports[i] = NULL; 40741edb306SCy Schubert } 40841edb306SCy Schubert free(tcp_ports); 40941edb306SCy Schubert tcp_ports = NULL; 41041edb306SCy Schubert } 41141edb306SCy Schubert tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 41241edb306SCy Schubert if (tcp_ports != NULL) 41341edb306SCy Schubert bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 41441edb306SCy Schubert 41541edb306SCy Schubert setservent(1); 41641edb306SCy Schubert while ((s = getservent()) != NULL) { 41741edb306SCy Schubert if (s->s_proto == NULL) 41841edb306SCy Schubert continue; 41941edb306SCy Schubert else if (!strcmp(s->s_proto, "tcp")) { 42041edb306SCy Schubert port = ntohs(s->s_port); 42141edb306SCy Schubert name = s->s_name; 42241edb306SCy Schubert tab = tcp_ports; 42341edb306SCy Schubert } else if (!strcmp(s->s_proto, "udp")) { 42441edb306SCy Schubert port = ntohs(s->s_port); 42541edb306SCy Schubert name = s->s_name; 42641edb306SCy Schubert tab = udp_ports; 42741edb306SCy Schubert } else 42841edb306SCy Schubert continue; 42941edb306SCy Schubert if ((port < 0 || port > 65535) || (name == NULL)) 43041edb306SCy Schubert continue; 43141edb306SCy Schubert if (tab != NULL) 43241edb306SCy Schubert tab[port] = strdup(name); 43341edb306SCy Schubert } 43441edb306SCy Schubert endservent(); 43541edb306SCy Schubert } 43641edb306SCy Schubert 43741edb306SCy Schubert 438efeb8bffSCy Schubert static char * 439efeb8bffSCy Schubert getlocalproto(u_int p) 44041edb306SCy Schubert { 44141edb306SCy Schubert static char pnum[4]; 44241edb306SCy Schubert char *s; 44341edb306SCy Schubert 44441edb306SCy Schubert p &= 0xff; 44541edb306SCy Schubert s = protocols ? protocols[p] : NULL; 44641edb306SCy Schubert if (s == NULL) { 447d740faa3SCy Schubert sprintf(pnum, "%u", p); 44841edb306SCy Schubert s = pnum; 44941edb306SCy Schubert } 4502582ae57SCy Schubert return (s); 45141edb306SCy Schubert } 45241edb306SCy Schubert 45341edb306SCy Schubert 454efeb8bffSCy Schubert static int 455efeb8bffSCy Schubert read_log(int fd, int *lenp, char *buf, int bufsize) 45641edb306SCy Schubert { 45741edb306SCy Schubert int nr; 45841edb306SCy Schubert 45941edb306SCy Schubert if (bufsize > IPFILTER_LOGSIZE) 46041edb306SCy Schubert bufsize = IPFILTER_LOGSIZE; 46141edb306SCy Schubert 46241edb306SCy Schubert nr = read(fd, buf, bufsize); 46341edb306SCy Schubert if (!nr) 4642582ae57SCy Schubert return (2); 46541edb306SCy Schubert if ((nr < 0) && (errno != EINTR)) 4662582ae57SCy Schubert return (-1); 46741edb306SCy Schubert *lenp = nr; 4682582ae57SCy Schubert return (0); 46941edb306SCy Schubert } 47041edb306SCy Schubert 47141edb306SCy Schubert 472efeb8bffSCy Schubert char * 473*2ac057ddSJohn Baldwin portlocalname(int res, char *proto, u_int port) 47441edb306SCy Schubert { 47541edb306SCy Schubert static char pname[8]; 47641edb306SCy Schubert char *s; 47741edb306SCy Schubert 47841edb306SCy Schubert port = ntohs(port); 47941edb306SCy Schubert port &= 0xffff; 480d740faa3SCy Schubert sprintf(pname, "%u", port); 48141edb306SCy Schubert if (!res || (ipmonopts & IPMON_PORTNUM)) 4822582ae57SCy Schubert return (pname); 48341edb306SCy Schubert s = NULL; 48441edb306SCy Schubert if (!strcmp(proto, "tcp")) 48541edb306SCy Schubert s = tcp_ports[port]; 48641edb306SCy Schubert else if (!strcmp(proto, "udp")) 48741edb306SCy Schubert s = udp_ports[port]; 48841edb306SCy Schubert if (s == NULL) 48941edb306SCy Schubert s = pname; 4902582ae57SCy Schubert return (s); 49141edb306SCy Schubert } 49241edb306SCy Schubert 49341edb306SCy Schubert 494efeb8bffSCy Schubert static char * 495efeb8bffSCy Schubert icmpname(u_int type, u_int code) 49641edb306SCy Schubert { 49741edb306SCy Schubert static char name[80]; 49841edb306SCy Schubert icmp_subtype_t *ist; 49941edb306SCy Schubert icmp_type_t *it; 50041edb306SCy Schubert char *s; 50141edb306SCy Schubert 50241edb306SCy Schubert s = NULL; 50341edb306SCy Schubert it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); 50441edb306SCy Schubert if (it != NULL) 50541edb306SCy Schubert s = it->it_name; 50641edb306SCy Schubert 50741edb306SCy Schubert if (s == NULL) 508d740faa3SCy Schubert sprintf(name, "icmptype(%d)/", type); 50941edb306SCy Schubert else 510d740faa3SCy Schubert sprintf(name, "%s/", s); 51141edb306SCy Schubert 51241edb306SCy Schubert ist = NULL; 51341edb306SCy Schubert if (it != NULL && it->it_subtable != NULL) 51441edb306SCy Schubert ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 51541edb306SCy Schubert 51641edb306SCy Schubert if (ist != NULL && ist->ist_name != NULL) 51741edb306SCy Schubert strcat(name, ist->ist_name); 518d740faa3SCy Schubert else 519d740faa3SCy Schubert sprintf(name + strlen(name), "%d", code); 52041edb306SCy Schubert 5212582ae57SCy Schubert return (name); 52241edb306SCy Schubert } 52341edb306SCy Schubert 524efeb8bffSCy Schubert static char * 525efeb8bffSCy Schubert icmpname6(u_int type, u_int code) 52641edb306SCy Schubert { 52741edb306SCy Schubert static char name[80]; 52841edb306SCy Schubert icmp_subtype_t *ist; 52941edb306SCy Schubert icmp_type_t *it; 53041edb306SCy Schubert char *s; 53141edb306SCy Schubert 53241edb306SCy Schubert s = NULL; 53341edb306SCy Schubert it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 53441edb306SCy Schubert if (it != NULL) 53541edb306SCy Schubert s = it->it_name; 53641edb306SCy Schubert 53741edb306SCy Schubert if (s == NULL) 538d740faa3SCy Schubert sprintf(name, "icmpv6type(%d)/", type); 53941edb306SCy Schubert else 540d740faa3SCy Schubert sprintf(name, "%s/", s); 54141edb306SCy Schubert 54241edb306SCy Schubert ist = NULL; 54341edb306SCy Schubert if (it != NULL && it->it_subtable != NULL) 54441edb306SCy Schubert ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 54541edb306SCy Schubert 54641edb306SCy Schubert if (ist != NULL && ist->ist_name != NULL) 54741edb306SCy Schubert strcat(name, ist->ist_name); 548d740faa3SCy Schubert else 549d740faa3SCy Schubert sprintf(name + strlen(name), "%d", code); 55041edb306SCy Schubert 5512582ae57SCy Schubert return (name); 55241edb306SCy Schubert } 55341edb306SCy Schubert 55441edb306SCy Schubert 555efeb8bffSCy Schubert void 556efeb8bffSCy Schubert dumphex(FILE *log, int dopts, char *buf, int len) 55741edb306SCy Schubert { 55841edb306SCy Schubert char hline[80]; 55941edb306SCy Schubert int i, j, k; 56041edb306SCy Schubert u_char *s = (u_char *)buf, *t = (u_char *)hline; 56141edb306SCy Schubert 56241edb306SCy Schubert if (buf == NULL || len == 0) 56341edb306SCy Schubert return; 56441edb306SCy Schubert 56541edb306SCy Schubert *hline = '\0'; 56641edb306SCy Schubert 56741edb306SCy Schubert for (i = len, j = 0; i; i--, j++, s++) { 56841edb306SCy Schubert if (j && !(j & 0xf)) { 56941edb306SCy Schubert *t++ = '\n'; 57041edb306SCy Schubert *t = '\0'; 57141edb306SCy Schubert if ((dopts & IPMON_SYSLOG)) 57241edb306SCy Schubert syslog(LOG_INFO, "%s", hline); 57341edb306SCy Schubert else if (log != NULL) 57441edb306SCy Schubert fputs(hline, log); 57541edb306SCy Schubert t = (u_char *)hline; 57641edb306SCy Schubert *t = '\0'; 57741edb306SCy Schubert } 57841edb306SCy Schubert sprintf((char *)t, "%02x", *s & 0xff); 57941edb306SCy Schubert t += 2; 58041edb306SCy Schubert if (!((j + 1) & 0xf)) { 58141edb306SCy Schubert s -= 15; 58241edb306SCy Schubert sprintf((char *)t, " "); 58341edb306SCy Schubert t += 8; 58441edb306SCy Schubert for (k = 16; k; k--, s++) 58541edb306SCy Schubert *t++ = (isprint(*s) ? *s : '.'); 58641edb306SCy Schubert s--; 58741edb306SCy Schubert } 58841edb306SCy Schubert 58941edb306SCy Schubert if ((j + 1) & 0xf) 59041edb306SCy Schubert *t++ = ' ';; 59141edb306SCy Schubert } 59241edb306SCy Schubert 59341edb306SCy Schubert if (j & 0xf) { 59441edb306SCy Schubert for (k = 16 - (j & 0xf); k; k--) { 59541edb306SCy Schubert *t++ = ' '; 59641edb306SCy Schubert *t++ = ' '; 59741edb306SCy Schubert *t++ = ' '; 59841edb306SCy Schubert } 59941edb306SCy Schubert sprintf((char *)t, " "); 60041edb306SCy Schubert t += 7; 60141edb306SCy Schubert s -= j & 0xf; 60241edb306SCy Schubert for (k = j & 0xf; k; k--, s++) 60341edb306SCy Schubert *t++ = (isprint(*s) ? *s : '.'); 60441edb306SCy Schubert *t++ = '\n'; 60541edb306SCy Schubert *t = '\0'; 60641edb306SCy Schubert } 60741edb306SCy Schubert if ((dopts & IPMON_SYSLOG) != 0) 60841edb306SCy Schubert syslog(LOG_INFO, "%s", hline); 60941edb306SCy Schubert else if (log != NULL) { 61041edb306SCy Schubert fputs(hline, log); 61141edb306SCy Schubert fflush(log); 61241edb306SCy Schubert } 61341edb306SCy Schubert } 61441edb306SCy Schubert 61541edb306SCy Schubert 616efeb8bffSCy Schubert static struct tm * 617efeb8bffSCy Schubert get_tm(time_t sec) 61841edb306SCy Schubert { 61941edb306SCy Schubert struct tm *tm; 62041edb306SCy Schubert time_t t; 62141edb306SCy Schubert 62241edb306SCy Schubert t = sec; 62341edb306SCy Schubert tm = localtime(&t); 6242582ae57SCy Schubert return (tm); 62541edb306SCy Schubert } 62641edb306SCy Schubert 627efeb8bffSCy Schubert static void 628efeb8bffSCy Schubert print_natlog(config_t *conf, char *buf, int blen) 62941edb306SCy Schubert { 63041edb306SCy Schubert static u_32_t seqnum = 0; 63141edb306SCy Schubert int res, i, len, family; 63241edb306SCy Schubert struct natlog *nl; 63341edb306SCy Schubert struct tm *tm; 63441edb306SCy Schubert iplog_t *ipl; 63541edb306SCy Schubert char *proto; 63641edb306SCy Schubert int simple; 63741edb306SCy Schubert char *t; 63841edb306SCy Schubert 63941edb306SCy Schubert t = line; 64041edb306SCy Schubert simple = 0; 64141edb306SCy Schubert ipl = (iplog_t *)buf; 64241edb306SCy Schubert if (ipl->ipl_seqnum != seqnum) { 64341edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG) != 0) { 64441edb306SCy Schubert syslog(LOG_WARNING, 64541edb306SCy Schubert "missed %u NAT log entries: %u %u", 64641edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 64741edb306SCy Schubert ipl->ipl_seqnum); 64841edb306SCy Schubert } else { 64941edb306SCy Schubert (void) fprintf(conf->log, 65041edb306SCy Schubert "missed %u NAT log entries: %u %u\n", 65141edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 65241edb306SCy Schubert ipl->ipl_seqnum); 65341edb306SCy Schubert } 65441edb306SCy Schubert } 65541edb306SCy Schubert seqnum = ipl->ipl_seqnum + ipl->ipl_count; 65641edb306SCy Schubert 65741edb306SCy Schubert nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 65841edb306SCy Schubert res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 65941edb306SCy Schubert tm = get_tm(ipl->ipl_sec); 66041edb306SCy Schubert len = sizeof(line); 66141edb306SCy Schubert 66241edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 66341edb306SCy Schubert (void) strftime(t, len, "%d/%m/%Y ", tm); 66441edb306SCy Schubert i = strlen(t); 66541edb306SCy Schubert len -= i; 66641edb306SCy Schubert t += i; 66741edb306SCy Schubert } 66841edb306SCy Schubert (void) strftime(t, len, "%T", tm); 66941edb306SCy Schubert t += strlen(t); 670d740faa3SCy Schubert sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); 67141edb306SCy Schubert t += strlen(t); 67241edb306SCy Schubert 67341edb306SCy Schubert switch (nl->nl_action) 67441edb306SCy Schubert { 67541edb306SCy Schubert case NL_NEW : 67641edb306SCy Schubert strcpy(t, "NAT:NEW"); 67741edb306SCy Schubert break; 67841edb306SCy Schubert 67941edb306SCy Schubert case NL_FLUSH : 68041edb306SCy Schubert strcpy(t, "NAT:FLUSH"); 68141edb306SCy Schubert break; 68241edb306SCy Schubert 68341edb306SCy Schubert case NL_CLONE : 68441edb306SCy Schubert strcpy(t, "NAT:CLONE"); 68541edb306SCy Schubert break; 68641edb306SCy Schubert 68741edb306SCy Schubert case NL_EXPIRE : 68841edb306SCy Schubert strcpy(t, "NAT:EXPIRE"); 68941edb306SCy Schubert break; 69041edb306SCy Schubert 69141edb306SCy Schubert case NL_DESTROY : 69241edb306SCy Schubert strcpy(t, "NAT:DESTROY"); 69341edb306SCy Schubert break; 69441edb306SCy Schubert 69541edb306SCy Schubert case NL_PURGE : 69641edb306SCy Schubert strcpy(t, "NAT:PURGE"); 69741edb306SCy Schubert break; 69841edb306SCy Schubert 69941edb306SCy Schubert default : 700d740faa3SCy Schubert sprintf(t, "NAT:Action(%d)", nl->nl_action); 70141edb306SCy Schubert break; 70241edb306SCy Schubert } 70341edb306SCy Schubert t += strlen(t); 70441edb306SCy Schubert 70541edb306SCy Schubert 70641edb306SCy Schubert switch (nl->nl_type) 70741edb306SCy Schubert { 70841edb306SCy Schubert case NAT_MAP : 70941edb306SCy Schubert strcpy(t, "-MAP "); 71041edb306SCy Schubert simple = 1; 71141edb306SCy Schubert break; 71241edb306SCy Schubert 71341edb306SCy Schubert case NAT_REDIRECT : 71441edb306SCy Schubert strcpy(t, "-RDR "); 71541edb306SCy Schubert simple = 1; 71641edb306SCy Schubert break; 71741edb306SCy Schubert 71841edb306SCy Schubert case NAT_BIMAP : 71941edb306SCy Schubert strcpy(t, "-BIMAP "); 72041edb306SCy Schubert simple = 1; 72141edb306SCy Schubert break; 72241edb306SCy Schubert 72341edb306SCy Schubert case NAT_MAPBLK : 72441edb306SCy Schubert strcpy(t, "-MAPBLOCK "); 72541edb306SCy Schubert simple = 1; 72641edb306SCy Schubert break; 72741edb306SCy Schubert 72841edb306SCy Schubert case NAT_REWRITE|NAT_MAP : 72941edb306SCy Schubert strcpy(t, "-RWR_MAP "); 73041edb306SCy Schubert break; 73141edb306SCy Schubert 73241edb306SCy Schubert case NAT_REWRITE|NAT_REDIRECT : 73341edb306SCy Schubert strcpy(t, "-RWR_RDR "); 73441edb306SCy Schubert break; 73541edb306SCy Schubert 73641edb306SCy Schubert case NAT_ENCAP|NAT_MAP : 73741edb306SCy Schubert strcpy(t, "-ENC_MAP "); 73841edb306SCy Schubert break; 73941edb306SCy Schubert 74041edb306SCy Schubert case NAT_ENCAP|NAT_REDIRECT : 74141edb306SCy Schubert strcpy(t, "-ENC_RDR "); 74241edb306SCy Schubert break; 74341edb306SCy Schubert 74441edb306SCy Schubert case NAT_DIVERTUDP|NAT_MAP : 74541edb306SCy Schubert strcpy(t, "-DIV_MAP "); 74641edb306SCy Schubert break; 74741edb306SCy Schubert 74841edb306SCy Schubert case NAT_DIVERTUDP|NAT_REDIRECT : 74941edb306SCy Schubert strcpy(t, "-DIV_RDR "); 75041edb306SCy Schubert break; 75141edb306SCy Schubert 75241edb306SCy Schubert default : 753d740faa3SCy Schubert sprintf(t, "-Type(%d) ", nl->nl_type); 75441edb306SCy Schubert break; 75541edb306SCy Schubert } 75641edb306SCy Schubert t += strlen(t); 75741edb306SCy Schubert 75841edb306SCy Schubert proto = getlocalproto(nl->nl_p[0]); 75941edb306SCy Schubert 76041edb306SCy Schubert family = vtof(nl->nl_v[0]); 76141edb306SCy Schubert 76241edb306SCy Schubert if (simple == 1) { 763d740faa3SCy Schubert sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6), 76441edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_osrcport)); 76541edb306SCy Schubert t += strlen(t); 766d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 76741edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 76841edb306SCy Schubert t += strlen(t); 769d740faa3SCy Schubert sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6), 77041edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_odstport)); 77141edb306SCy Schubert } else { 772d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6), 77341edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_osrcport)); 77441edb306SCy Schubert t += strlen(t); 775d740faa3SCy Schubert sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6), 77641edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_odstport)); 77741edb306SCy Schubert t += strlen(t); 778d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 77941edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 78041edb306SCy Schubert t += strlen(t); 781d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6), 78241edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_ndstport)); 78341edb306SCy Schubert } 78441edb306SCy Schubert t += strlen(t); 78541edb306SCy Schubert 78641edb306SCy Schubert strcpy(t, getlocalproto(nl->nl_p[0])); 78741edb306SCy Schubert t += strlen(t); 78841edb306SCy Schubert 78941edb306SCy Schubert if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { 79041edb306SCy Schubert #ifdef USE_QUAD_T 79141edb306SCy Schubert # ifdef PRId64 792d740faa3SCy Schubert sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" 79341edb306SCy Schubert PRId64, 79441edb306SCy Schubert # else 795d740faa3SCy Schubert sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 79641edb306SCy Schubert # endif 79741edb306SCy Schubert #else 798d740faa3SCy Schubert sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 79941edb306SCy Schubert #endif 80041edb306SCy Schubert nl->nl_pkts[0], nl->nl_pkts[1], 80141edb306SCy Schubert nl->nl_bytes[0], nl->nl_bytes[1]); 80241edb306SCy Schubert t += strlen(t); 80341edb306SCy Schubert } 80441edb306SCy Schubert 80541edb306SCy Schubert *t++ = '\n'; 80641edb306SCy Schubert *t++ = '\0'; 80741edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 80841edb306SCy Schubert syslog(LOG_INFO, "%s", line); 80941edb306SCy Schubert else if (conf->log != NULL) 81041edb306SCy Schubert (void) fprintf(conf->log, "%s", line); 81141edb306SCy Schubert } 81241edb306SCy Schubert 81341edb306SCy Schubert 814efeb8bffSCy Schubert static void 815efeb8bffSCy Schubert print_statelog(config_t *conf, char *buf, int blen) 81641edb306SCy Schubert { 81741edb306SCy Schubert static u_32_t seqnum = 0; 81841edb306SCy Schubert int res, i, len, family; 81941edb306SCy Schubert struct ipslog *sl; 82041edb306SCy Schubert char *t, *proto; 82141edb306SCy Schubert struct tm *tm; 82241edb306SCy Schubert iplog_t *ipl; 82341edb306SCy Schubert 82441edb306SCy Schubert t = line; 82541edb306SCy Schubert ipl = (iplog_t *)buf; 82641edb306SCy Schubert if (ipl->ipl_seqnum != seqnum) { 82741edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG) != 0) { 82841edb306SCy Schubert syslog(LOG_WARNING, 82941edb306SCy Schubert "missed %u state log entries: %u %u", 83041edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 83141edb306SCy Schubert ipl->ipl_seqnum); 83241edb306SCy Schubert } else { 83341edb306SCy Schubert (void) fprintf(conf->log, 83441edb306SCy Schubert "missed %u state log entries: %u %u\n", 83541edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 83641edb306SCy Schubert ipl->ipl_seqnum); 83741edb306SCy Schubert } 83841edb306SCy Schubert } 83941edb306SCy Schubert seqnum = ipl->ipl_seqnum + ipl->ipl_count; 84041edb306SCy Schubert 84141edb306SCy Schubert sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 84241edb306SCy Schubert res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 84341edb306SCy Schubert tm = get_tm(ipl->ipl_sec); 84441edb306SCy Schubert len = sizeof(line); 84541edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 84641edb306SCy Schubert (void) strftime(t, len, "%d/%m/%Y ", tm); 84741edb306SCy Schubert i = strlen(t); 84841edb306SCy Schubert len -= i; 84941edb306SCy Schubert t += i; 85041edb306SCy Schubert } 85141edb306SCy Schubert (void) strftime(t, len, "%T", tm); 85241edb306SCy Schubert t += strlen(t); 853d740faa3SCy Schubert sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 85441edb306SCy Schubert t += strlen(t); 85541edb306SCy Schubert 85641edb306SCy Schubert family = vtof(sl->isl_v); 85741edb306SCy Schubert 85841edb306SCy Schubert switch (sl->isl_type) 85941edb306SCy Schubert { 86041edb306SCy Schubert case ISL_NEW : 86141edb306SCy Schubert strcpy(t, "STATE:NEW "); 86241edb306SCy Schubert break; 86341edb306SCy Schubert 86441edb306SCy Schubert case ISL_CLONE : 86541edb306SCy Schubert strcpy(t, "STATE:CLONED "); 86641edb306SCy Schubert break; 86741edb306SCy Schubert 86841edb306SCy Schubert case ISL_EXPIRE : 86941edb306SCy Schubert if ((sl->isl_p == IPPROTO_TCP) && 87041edb306SCy Schubert (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 87141edb306SCy Schubert sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 87241edb306SCy Schubert strcpy(t, "STATE:CLOSE "); 87341edb306SCy Schubert else 87441edb306SCy Schubert strcpy(t, "STATE:EXPIRE "); 87541edb306SCy Schubert break; 87641edb306SCy Schubert 87741edb306SCy Schubert case ISL_FLUSH : 87841edb306SCy Schubert strcpy(t, "STATE:FLUSH "); 87941edb306SCy Schubert break; 88041edb306SCy Schubert 88141edb306SCy Schubert case ISL_INTERMEDIATE : 88241edb306SCy Schubert strcpy(t, "STATE:INTERMEDIATE "); 88341edb306SCy Schubert break; 88441edb306SCy Schubert 88541edb306SCy Schubert case ISL_REMOVE : 88641edb306SCy Schubert strcpy(t, "STATE:REMOVE "); 88741edb306SCy Schubert break; 88841edb306SCy Schubert 88941edb306SCy Schubert case ISL_KILLED : 89041edb306SCy Schubert strcpy(t, "STATE:KILLED "); 89141edb306SCy Schubert break; 89241edb306SCy Schubert 89341edb306SCy Schubert case ISL_UNLOAD : 89441edb306SCy Schubert strcpy(t, "STATE:UNLOAD "); 89541edb306SCy Schubert break; 89641edb306SCy Schubert 89741edb306SCy Schubert default : 898d740faa3SCy Schubert sprintf(t, "Type: %d ", sl->isl_type); 89941edb306SCy Schubert break; 90041edb306SCy Schubert } 90141edb306SCy Schubert t += strlen(t); 90241edb306SCy Schubert 90341edb306SCy Schubert proto = getlocalproto(sl->isl_p); 90441edb306SCy Schubert 90541edb306SCy Schubert if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 906d740faa3SCy Schubert sprintf(t, "%s,%s -> ", 90741edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_src), 90841edb306SCy Schubert portlocalname(res, proto, (u_int)sl->isl_sport)); 90941edb306SCy Schubert t += strlen(t); 910d740faa3SCy Schubert sprintf(t, "%s,%s PR %s", 91141edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), 91241edb306SCy Schubert portlocalname(res, proto, (u_int)sl->isl_dport), proto); 91341edb306SCy Schubert } else if (sl->isl_p == IPPROTO_ICMP) { 914d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 91541edb306SCy Schubert t += strlen(t); 916d740faa3SCy Schubert sprintf(t, "%s PR icmp %d", 91741edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), 91841edb306SCy Schubert sl->isl_itype); 91941edb306SCy Schubert } else if (sl->isl_p == IPPROTO_ICMPV6) { 920d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 92141edb306SCy Schubert t += strlen(t); 922d740faa3SCy Schubert sprintf(t, "%s PR icmpv6 %d", 92341edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), 92441edb306SCy Schubert sl->isl_itype); 92541edb306SCy Schubert } else { 926d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 92741edb306SCy Schubert t += strlen(t); 928d740faa3SCy Schubert sprintf(t, "%s PR %s", 92941edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), proto); 93041edb306SCy Schubert } 93141edb306SCy Schubert t += strlen(t); 93241edb306SCy Schubert if (sl->isl_tag != FR_NOLOGTAG) { 933d740faa3SCy Schubert sprintf(t, " tag %u", sl->isl_tag); 93441edb306SCy Schubert t += strlen(t); 93541edb306SCy Schubert } 93641edb306SCy Schubert if (sl->isl_type != ISL_NEW) { 937d740faa3SCy Schubert sprintf(t, 93841edb306SCy Schubert #ifdef USE_QUAD_T 93941edb306SCy Schubert #ifdef PRId64 94041edb306SCy Schubert " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 94141edb306SCy Schubert " Pkts out %" PRId64 " Bytes out %" PRId64 94241edb306SCy Schubert " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 94341edb306SCy Schubert " Pkts out %" PRId64 " Bytes out %" PRId64, 94441edb306SCy Schubert #else 94541edb306SCy Schubert " 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", 94641edb306SCy Schubert #endif /* PRId64 */ 94741edb306SCy Schubert #else 94841edb306SCy Schubert " 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", 94941edb306SCy Schubert #endif 95041edb306SCy Schubert sl->isl_pkts[0], sl->isl_bytes[0], 95141edb306SCy Schubert sl->isl_pkts[1], sl->isl_bytes[1], 95241edb306SCy Schubert sl->isl_pkts[2], sl->isl_bytes[2], 95341edb306SCy Schubert sl->isl_pkts[3], sl->isl_bytes[3]); 95441edb306SCy Schubert 95541edb306SCy Schubert t += strlen(t); 95641edb306SCy Schubert } 95741edb306SCy Schubert 95841edb306SCy Schubert *t++ = '\n'; 95941edb306SCy Schubert *t++ = '\0'; 96041edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 96141edb306SCy Schubert syslog(LOG_INFO, "%s", line); 96241edb306SCy Schubert else if (conf->log != NULL) 96341edb306SCy Schubert (void) fprintf(conf->log, "%s", line); 96441edb306SCy Schubert } 96541edb306SCy Schubert 96641edb306SCy Schubert 967efeb8bffSCy Schubert static void 968efeb8bffSCy Schubert print_log(config_t *conf, logsource_t *log, char *buf, int blen) 96941edb306SCy Schubert { 97041edb306SCy Schubert char *bp, *bpo; 97141edb306SCy Schubert iplog_t *ipl; 97241edb306SCy Schubert int psize; 97341edb306SCy Schubert 97441edb306SCy Schubert bp = NULL; 97541edb306SCy Schubert bpo = NULL; 97641edb306SCy Schubert 97741edb306SCy Schubert while (blen > 0) { 97841edb306SCy Schubert ipl = (iplog_t *)buf; 97941edb306SCy Schubert if ((u_long)ipl & (sizeof(long)-1)) { 98041edb306SCy Schubert if (bp) 98141edb306SCy Schubert bpo = bp; 98241edb306SCy Schubert bp = (char *)malloc(blen); 98341edb306SCy Schubert bcopy((char *)ipl, bp, blen); 98441edb306SCy Schubert if (bpo) { 98541edb306SCy Schubert free(bpo); 98641edb306SCy Schubert bpo = NULL; 98741edb306SCy Schubert } 98841edb306SCy Schubert buf = bp; 98941edb306SCy Schubert continue; 99041edb306SCy Schubert } 99141edb306SCy Schubert 99241edb306SCy Schubert psize = ipl->ipl_dsize; 99341edb306SCy Schubert if (psize > blen) 99441edb306SCy Schubert break; 99541edb306SCy Schubert 99641edb306SCy Schubert if (conf->blog != NULL) { 99741edb306SCy Schubert fwrite(buf, psize, 1, conf->blog); 99841edb306SCy Schubert fflush(conf->blog); 99941edb306SCy Schubert } 100041edb306SCy Schubert 100141edb306SCy Schubert if (log->logtype == IPL_LOGIPF) { 100241edb306SCy Schubert if (ipl->ipl_magic == IPL_MAGIC) 100341edb306SCy Schubert print_ipflog(conf, buf, psize); 100441edb306SCy Schubert 100541edb306SCy Schubert } else if (log->logtype == IPL_LOGNAT) { 100641edb306SCy Schubert if (ipl->ipl_magic == IPL_MAGIC_NAT) 100741edb306SCy Schubert print_natlog(conf, buf, psize); 100841edb306SCy Schubert 100941edb306SCy Schubert } else if (log->logtype == IPL_LOGSTATE) { 101041edb306SCy Schubert if (ipl->ipl_magic == IPL_MAGIC_STATE) 101141edb306SCy Schubert print_statelog(conf, buf, psize); 101241edb306SCy Schubert } 101341edb306SCy Schubert 101441edb306SCy Schubert blen -= psize; 101541edb306SCy Schubert buf += psize; 101641edb306SCy Schubert } 101741edb306SCy Schubert if (bp) 101841edb306SCy Schubert free(bp); 101941edb306SCy Schubert return; 102041edb306SCy Schubert } 102141edb306SCy Schubert 102241edb306SCy Schubert 1023efeb8bffSCy Schubert static void 1024efeb8bffSCy Schubert print_ipflog(config_t *conf, char *buf, int blen) 102541edb306SCy Schubert { 102641edb306SCy Schubert static u_32_t seqnum = 0; 102741edb306SCy Schubert int i, f, lvl, res, len, off, plen, ipoff, defaction; 102841edb306SCy Schubert struct icmp *icmp; 102941edb306SCy Schubert struct icmp *ic; 103041edb306SCy Schubert char *t, *proto; 103141edb306SCy Schubert ip_t *ipc, *ip; 103241edb306SCy Schubert struct tm *tm; 103341edb306SCy Schubert u_32_t *s, *d; 103441edb306SCy Schubert u_short hl, p; 103541edb306SCy Schubert ipflog_t *ipf; 103641edb306SCy Schubert iplog_t *ipl; 103741edb306SCy Schubert tcphdr_t *tp; 103841edb306SCy Schubert #ifdef USE_INET6 103941edb306SCy Schubert struct ip6_ext *ehp; 104041edb306SCy Schubert u_short ehl; 104141edb306SCy Schubert ip6_t *ip6; 104241edb306SCy Schubert int go; 104341edb306SCy Schubert #endif 104441edb306SCy Schubert 104541edb306SCy Schubert ipl = (iplog_t *)buf; 104641edb306SCy Schubert if (ipl->ipl_seqnum != seqnum) { 104741edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG) != 0) { 104841edb306SCy Schubert syslog(LOG_WARNING, 104941edb306SCy Schubert "missed %u ipf log entries: %u %u", 105041edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 105141edb306SCy Schubert ipl->ipl_seqnum); 105241edb306SCy Schubert } else { 105341edb306SCy Schubert (void) fprintf(conf->log, 105441edb306SCy Schubert "missed %u ipf log entries: %u %u\n", 105541edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 105641edb306SCy Schubert ipl->ipl_seqnum); 105741edb306SCy Schubert } 105841edb306SCy Schubert } 105941edb306SCy Schubert seqnum = ipl->ipl_seqnum + ipl->ipl_count; 106041edb306SCy Schubert 106141edb306SCy Schubert ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 106241edb306SCy Schubert ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 106341edb306SCy Schubert f = ipf->fl_family; 106441edb306SCy Schubert res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 106541edb306SCy Schubert t = line; 106641edb306SCy Schubert *t = '\0'; 106741edb306SCy Schubert tm = get_tm(ipl->ipl_sec); 106841edb306SCy Schubert 106941edb306SCy Schubert len = sizeof(line); 107041edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 107141edb306SCy Schubert (void) strftime(t, len, "%d/%m/%Y ", tm); 107241edb306SCy Schubert i = strlen(t); 107341edb306SCy Schubert len -= i; 107441edb306SCy Schubert t += i; 107541edb306SCy Schubert } 107641edb306SCy Schubert (void) strftime(t, len, "%T", tm); 107741edb306SCy Schubert t += strlen(t); 1078d740faa3SCy Schubert sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 107941edb306SCy Schubert t += strlen(t); 108041edb306SCy Schubert if (ipl->ipl_count > 1) { 1081d740faa3SCy Schubert sprintf(t, "%dx ", ipl->ipl_count); 108241edb306SCy Schubert t += strlen(t); 108341edb306SCy Schubert } 108441edb306SCy Schubert { 108541edb306SCy Schubert char ifname[sizeof(ipf->fl_ifname) + 1]; 108641edb306SCy Schubert 108741edb306SCy Schubert strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 108841edb306SCy Schubert ifname[sizeof(ipf->fl_ifname)] = '\0'; 1089d740faa3SCy Schubert sprintf(t, "%s", ifname); 109041edb306SCy Schubert t += strlen(t); 109141edb306SCy Schubert # if SOLARIS 109241edb306SCy Schubert if (ISALPHA(*(t - 1))) { 1093d740faa3SCy Schubert sprintf(t, "%d", ipf->fl_unit); 109441edb306SCy Schubert t += strlen(t); 109541edb306SCy Schubert } 109641edb306SCy Schubert # endif 109741edb306SCy Schubert } 109841edb306SCy Schubert if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) 109941edb306SCy Schubert strcat(t, " @-1:"); 110041edb306SCy Schubert else if (ipf->fl_group[0] == '\0') 110141edb306SCy Schubert (void) strcpy(t, " @0:"); 110241edb306SCy Schubert else 1103d740faa3SCy Schubert sprintf(t, " @%s:", ipf->fl_group); 110441edb306SCy Schubert t += strlen(t); 110541edb306SCy Schubert if (ipf->fl_rule == 0xffffffff) 110641edb306SCy Schubert strcat(t, "-1 "); 110741edb306SCy Schubert else 1108d740faa3SCy Schubert sprintf(t, "%u ", ipf->fl_rule + 1); 110941edb306SCy Schubert t += strlen(t); 111041edb306SCy Schubert 111141edb306SCy Schubert lvl = LOG_NOTICE; 111241edb306SCy Schubert 111341edb306SCy Schubert if (ipf->fl_lflags & FI_SHORT) { 111441edb306SCy Schubert *t++ = 'S'; 111541edb306SCy Schubert lvl = LOG_ERR; 111641edb306SCy Schubert } 111741edb306SCy Schubert 111841edb306SCy Schubert if (FR_ISPASS(ipf->fl_flags)) { 111941edb306SCy Schubert if (ipf->fl_flags & FR_LOGP) 112041edb306SCy Schubert *t++ = 'p'; 112141edb306SCy Schubert else 112241edb306SCy Schubert *t++ = 'P'; 112341edb306SCy Schubert } else if (FR_ISBLOCK(ipf->fl_flags)) { 112441edb306SCy Schubert if (ipf->fl_flags & FR_LOGB) 112541edb306SCy Schubert *t++ = 'b'; 112641edb306SCy Schubert else 112741edb306SCy Schubert *t++ = 'B'; 112841edb306SCy Schubert lvl = LOG_WARNING; 112941edb306SCy Schubert } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 113041edb306SCy Schubert *t++ = 'L'; 113141edb306SCy Schubert lvl = LOG_INFO; 113241edb306SCy Schubert } else if (ipf->fl_flags & FF_LOGNOMATCH) { 113341edb306SCy Schubert *t++ = 'n'; 113441edb306SCy Schubert } else { 113541edb306SCy Schubert *t++ = '?'; 113641edb306SCy Schubert lvl = LOG_EMERG; 113741edb306SCy Schubert } 113841edb306SCy Schubert if (ipf->fl_loglevel != 0xffff) 113941edb306SCy Schubert lvl = ipf->fl_loglevel; 114041edb306SCy Schubert *t++ = ' '; 114141edb306SCy Schubert *t = '\0'; 114241edb306SCy Schubert 114341edb306SCy Schubert if (f == AF_INET) { 114441edb306SCy Schubert hl = IP_HL(ip) << 2; 114541edb306SCy Schubert ipoff = ntohs(ip->ip_off); 114641edb306SCy Schubert off = ipoff & IP_OFFMASK; 114741edb306SCy Schubert p = (u_short)ip->ip_p; 114841edb306SCy Schubert s = (u_32_t *)&ip->ip_src; 114941edb306SCy Schubert d = (u_32_t *)&ip->ip_dst; 115041edb306SCy Schubert plen = ntohs(ip->ip_len); 115141edb306SCy Schubert } else 115241edb306SCy Schubert #ifdef USE_INET6 115341edb306SCy Schubert if (f == AF_INET6) { 115441edb306SCy Schubert off = 0; 115541edb306SCy Schubert ipoff = 0; 115641edb306SCy Schubert hl = sizeof(ip6_t); 115741edb306SCy Schubert ip6 = (ip6_t *)ip; 115841edb306SCy Schubert p = (u_short)ip6->ip6_nxt; 115941edb306SCy Schubert s = (u_32_t *)&ip6->ip6_src; 116041edb306SCy Schubert d = (u_32_t *)&ip6->ip6_dst; 116141edb306SCy Schubert plen = hl + ntohs(ip6->ip6_plen); 116241edb306SCy Schubert go = 1; 116341edb306SCy Schubert ehp = (struct ip6_ext *)((char *)ip6 + hl); 116441edb306SCy Schubert while (go == 1) { 116541edb306SCy Schubert switch (p) 116641edb306SCy Schubert { 116741edb306SCy Schubert case IPPROTO_HOPOPTS : 116841edb306SCy Schubert case IPPROTO_MOBILITY : 116941edb306SCy Schubert case IPPROTO_DSTOPTS : 117041edb306SCy Schubert case IPPROTO_ROUTING : 117141edb306SCy Schubert case IPPROTO_AH : 117241edb306SCy Schubert p = ehp->ip6e_nxt; 117341edb306SCy Schubert ehl = 8 + (ehp->ip6e_len << 3); 117441edb306SCy Schubert hl += ehl; 117541edb306SCy Schubert ehp = (struct ip6_ext *)((char *)ehp + ehl); 117641edb306SCy Schubert break; 117741edb306SCy Schubert case IPPROTO_FRAGMENT : 117841edb306SCy Schubert hl += sizeof(struct ip6_frag); 117941edb306SCy Schubert /* FALLTHROUGH */ 118041edb306SCy Schubert default : 118141edb306SCy Schubert go = 0; 118241edb306SCy Schubert break; 118341edb306SCy Schubert } 118441edb306SCy Schubert } 118541edb306SCy Schubert } else 118641edb306SCy Schubert #endif 118741edb306SCy Schubert { 118841edb306SCy Schubert goto printipflog; 118941edb306SCy Schubert } 119041edb306SCy Schubert proto = getlocalproto(p); 119141edb306SCy Schubert 119241edb306SCy Schubert if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 119341edb306SCy Schubert tp = (tcphdr_t *)((char *)ip + hl); 119441edb306SCy Schubert if (!(ipf->fl_lflags & FI_SHORT)) { 1195d740faa3SCy Schubert sprintf(t, "%s,%s -> ", hostname(f, s), 119641edb306SCy Schubert portlocalname(res, proto, (u_int)tp->th_sport)); 119741edb306SCy Schubert t += strlen(t); 1198d740faa3SCy Schubert sprintf(t, "%s,%s PR %s len %hu %hu", 119941edb306SCy Schubert hostname(f, d), 120041edb306SCy Schubert portlocalname(res, proto, (u_int)tp->th_dport), 120141edb306SCy Schubert proto, hl, plen); 120241edb306SCy Schubert t += strlen(t); 120341edb306SCy Schubert 120441edb306SCy Schubert if (p == IPPROTO_TCP) { 120541edb306SCy Schubert *t++ = ' '; 120641edb306SCy Schubert *t++ = '-'; 120741edb306SCy Schubert for (i = 0; tcpfl[i].value; i++) 120841edb306SCy Schubert if (tp->th_flags & tcpfl[i].value) 120941edb306SCy Schubert *t++ = tcpfl[i].flag; 121041edb306SCy Schubert if (ipmonopts & IPMON_VERBOSE) { 1211d740faa3SCy Schubert sprintf(t, " %lu %lu %hu", 121241edb306SCy Schubert (u_long)(ntohl(tp->th_seq)), 121341edb306SCy Schubert (u_long)(ntohl(tp->th_ack)), 121441edb306SCy Schubert ntohs(tp->th_win)); 121541edb306SCy Schubert t += strlen(t); 121641edb306SCy Schubert } 121741edb306SCy Schubert } 121841edb306SCy Schubert *t = '\0'; 121941edb306SCy Schubert } else { 1220d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 122141edb306SCy Schubert t += strlen(t); 122241edb306SCy Schubert sprintf(t, "%s PR %s len %hu %hu", 122341edb306SCy Schubert hostname(f, d), proto, hl, plen); 122441edb306SCy Schubert } 122541edb306SCy Schubert #if defined(AF_INET6) && defined(IPPROTO_ICMPV6) 122641edb306SCy Schubert } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { 122741edb306SCy Schubert ic = (struct icmp *)((char *)ip + hl); 1228d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 122941edb306SCy Schubert t += strlen(t); 1230d740faa3SCy Schubert sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 123141edb306SCy Schubert hostname(f, d), hl, plen, 123241edb306SCy Schubert icmpname6(ic->icmp_type, ic->icmp_code)); 123341edb306SCy Schubert #endif 123441edb306SCy Schubert } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { 123541edb306SCy Schubert ic = (struct icmp *)((char *)ip + hl); 1236d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 123741edb306SCy Schubert t += strlen(t); 1238d740faa3SCy Schubert sprintf(t, "%s PR icmp len %hu %hu icmp %s", 123941edb306SCy Schubert hostname(f, d), hl, plen, 124041edb306SCy Schubert icmpname(ic->icmp_type, ic->icmp_code)); 124141edb306SCy Schubert if (ic->icmp_type == ICMP_UNREACH || 124241edb306SCy Schubert ic->icmp_type == ICMP_SOURCEQUENCH || 124341edb306SCy Schubert ic->icmp_type == ICMP_PARAMPROB || 124441edb306SCy Schubert ic->icmp_type == ICMP_REDIRECT || 124541edb306SCy Schubert ic->icmp_type == ICMP_TIMXCEED) { 124641edb306SCy Schubert ipc = &ic->icmp_ip; 124741edb306SCy Schubert i = ntohs(ipc->ip_len); 124841edb306SCy Schubert /* 124941edb306SCy Schubert * XXX - try to guess endian of ip_len in ICMP 125041edb306SCy Schubert * returned data. 125141edb306SCy Schubert */ 125241edb306SCy Schubert if (i > 1500) 125341edb306SCy Schubert i = ipc->ip_len; 125441edb306SCy Schubert ipoff = ntohs(ipc->ip_off); 125541edb306SCy Schubert proto = getlocalproto(ipc->ip_p); 125641edb306SCy Schubert 125741edb306SCy Schubert if (!(ipoff & IP_OFFMASK) && 125841edb306SCy Schubert ((ipc->ip_p == IPPROTO_TCP) || 125941edb306SCy Schubert (ipc->ip_p == IPPROTO_UDP))) { 126041edb306SCy Schubert tp = (tcphdr_t *)((char *)ipc + hl); 126141edb306SCy Schubert t += strlen(t); 1262d740faa3SCy Schubert sprintf(t, " for %s,%s -", 126341edb306SCy Schubert HOSTNAMEV4(ipc->ip_src), 126441edb306SCy Schubert portlocalname(res, proto, 126541edb306SCy Schubert (u_int)tp->th_sport)); 126641edb306SCy Schubert t += strlen(t); 1267d740faa3SCy Schubert sprintf(t, " %s,%s PR %s len %hu %hu", 126841edb306SCy Schubert HOSTNAMEV4(ipc->ip_dst), 126941edb306SCy Schubert portlocalname(res, proto, 127041edb306SCy Schubert (u_int)tp->th_dport), 127141edb306SCy Schubert proto, IP_HL(ipc) << 2, i); 127241edb306SCy Schubert } else if (!(ipoff & IP_OFFMASK) && 127341edb306SCy Schubert (ipc->ip_p == IPPROTO_ICMP)) { 127441edb306SCy Schubert icmp = (icmphdr_t *)((char *)ipc + hl); 127541edb306SCy Schubert 127641edb306SCy Schubert t += strlen(t); 1277d740faa3SCy Schubert sprintf(t, " for %s -", 127841edb306SCy Schubert HOSTNAMEV4(ipc->ip_src)); 127941edb306SCy Schubert t += strlen(t); 1280d740faa3SCy Schubert sprintf(t, 128141edb306SCy Schubert " %s PR icmp len %hu %hu icmp %d/%d", 128241edb306SCy Schubert HOSTNAMEV4(ipc->ip_dst), 128341edb306SCy Schubert IP_HL(ipc) << 2, i, 128441edb306SCy Schubert icmp->icmp_type, icmp->icmp_code); 128541edb306SCy Schubert } else { 128641edb306SCy Schubert t += strlen(t); 1287d740faa3SCy Schubert sprintf(t, " for %s -", 128841edb306SCy Schubert HOSTNAMEV4(ipc->ip_src)); 128941edb306SCy Schubert t += strlen(t); 1290d740faa3SCy Schubert sprintf(t, " %s PR %s len %hu (%hu)", 129141edb306SCy Schubert HOSTNAMEV4(ipc->ip_dst), proto, 129241edb306SCy Schubert IP_HL(ipc) << 2, i); 129341edb306SCy Schubert t += strlen(t); 129441edb306SCy Schubert if (ipoff & IP_OFFMASK) { 1295d740faa3SCy Schubert sprintf(t, "(frag %d:%hu@%hu%s%s)", 129641edb306SCy Schubert ntohs(ipc->ip_id), 129741edb306SCy Schubert i - (IP_HL(ipc) << 2), 129841edb306SCy Schubert (ipoff & IP_OFFMASK) << 3, 129941edb306SCy Schubert ipoff & IP_MF ? "+" : "", 130041edb306SCy Schubert ipoff & IP_DF ? "-" : ""); 130141edb306SCy Schubert } 130241edb306SCy Schubert } 130341edb306SCy Schubert 130441edb306SCy Schubert } 130541edb306SCy Schubert } else { 1306d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 130741edb306SCy Schubert t += strlen(t); 1308d740faa3SCy Schubert sprintf(t, "%s PR %s len %hu (%hu)", 130941edb306SCy Schubert hostname(f, d), proto, hl, plen); 131041edb306SCy Schubert t += strlen(t); 131141edb306SCy Schubert if (off & IP_OFFMASK) 1312d740faa3SCy Schubert sprintf(t, " (frag %d:%hu@%hu%s%s)", 131341edb306SCy Schubert ntohs(ip->ip_id), 131441edb306SCy Schubert plen - hl, (off & IP_OFFMASK) << 3, 131541edb306SCy Schubert ipoff & IP_MF ? "+" : "", 131641edb306SCy Schubert ipoff & IP_DF ? "-" : ""); 131741edb306SCy Schubert } 131841edb306SCy Schubert t += strlen(t); 131941edb306SCy Schubert 132041edb306SCy Schubert printipflog: 132141edb306SCy Schubert if (ipf->fl_flags & FR_KEEPSTATE) { 132241edb306SCy Schubert (void) strcpy(t, " K-S"); 132341edb306SCy Schubert t += strlen(t); 132441edb306SCy Schubert } 132541edb306SCy Schubert 132641edb306SCy Schubert if (ipf->fl_flags & FR_KEEPFRAG) { 132741edb306SCy Schubert (void) strcpy(t, " K-F"); 132841edb306SCy Schubert t += strlen(t); 132941edb306SCy Schubert } 133041edb306SCy Schubert 133141edb306SCy Schubert if (ipf->fl_dir == 0) 133241edb306SCy Schubert strcpy(t, " IN"); 133341edb306SCy Schubert else if (ipf->fl_dir == 1) 133441edb306SCy Schubert strcpy(t, " OUT"); 133541edb306SCy Schubert t += strlen(t); 133641edb306SCy Schubert if (ipf->fl_logtag != 0) { 1337d740faa3SCy Schubert sprintf(t, " log-tag %d", ipf->fl_logtag); 133841edb306SCy Schubert t += strlen(t); 133941edb306SCy Schubert } 134041edb306SCy Schubert if (ipf->fl_nattag.ipt_num[0] != 0) { 134141edb306SCy Schubert strcpy(t, " nat-tag "); 134241edb306SCy Schubert t += strlen(t); 134341edb306SCy Schubert strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 134441edb306SCy Schubert t += strlen(t); 134541edb306SCy Schubert } 134641edb306SCy Schubert if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 134741edb306SCy Schubert strcpy(t, " low-ttl"); 134841edb306SCy Schubert t += 8; 134941edb306SCy Schubert } 135041edb306SCy Schubert if ((ipf->fl_lflags & FI_OOW) != 0) { 135141edb306SCy Schubert strcpy(t, " OOW"); 135241edb306SCy Schubert t += 4; 135341edb306SCy Schubert } 135441edb306SCy Schubert if ((ipf->fl_lflags & FI_BAD) != 0) { 135541edb306SCy Schubert strcpy(t, " bad"); 135641edb306SCy Schubert t += 4; 135741edb306SCy Schubert } 135841edb306SCy Schubert if ((ipf->fl_lflags & FI_NATED) != 0) { 135941edb306SCy Schubert strcpy(t, " NAT"); 136041edb306SCy Schubert t += 4; 136141edb306SCy Schubert } 136241edb306SCy Schubert if ((ipf->fl_lflags & FI_BADNAT) != 0) { 136341edb306SCy Schubert strcpy(t, " bad-NAT"); 136441edb306SCy Schubert t += 8; 136541edb306SCy Schubert } 136641edb306SCy Schubert if ((ipf->fl_lflags & FI_BADSRC) != 0) { 136741edb306SCy Schubert strcpy(t, " bad-src"); 136841edb306SCy Schubert t += 8; 136941edb306SCy Schubert } 137041edb306SCy Schubert if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 137141edb306SCy Schubert strcpy(t, " multicast"); 137241edb306SCy Schubert t += 10; 137341edb306SCy Schubert } 137441edb306SCy Schubert if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 137541edb306SCy Schubert strcpy(t, " broadcast"); 137641edb306SCy Schubert t += 10; 137741edb306SCy Schubert } 137841edb306SCy Schubert if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 137941edb306SCy Schubert FI_MBCAST) { 138041edb306SCy Schubert strcpy(t, " mbcast"); 138141edb306SCy Schubert t += 7; 138241edb306SCy Schubert } 138341edb306SCy Schubert if (ipf->fl_breason != 0) { 138441edb306SCy Schubert strcpy(t, " reason:"); 138541edb306SCy Schubert t += 8; 138641edb306SCy Schubert strcpy(t, reasons[ipf->fl_breason]); 138741edb306SCy Schubert t += strlen(reasons[ipf->fl_breason]); 138841edb306SCy Schubert } 138941edb306SCy Schubert *t++ = '\n'; 139041edb306SCy Schubert *t++ = '\0'; 139141edb306SCy Schubert defaction = 0; 139241edb306SCy Schubert if (conf->cfile != NULL) 139341edb306SCy Schubert defaction = check_action(buf, line, ipmonopts, lvl); 139441edb306SCy Schubert 139541edb306SCy Schubert if (defaction == 0) { 139641edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) { 139741edb306SCy Schubert syslog(lvl, "%s", line); 139841edb306SCy Schubert } else if (conf->log != NULL) { 139941edb306SCy Schubert (void) fprintf(conf->log, "%s", line); 140041edb306SCy Schubert } 140141edb306SCy Schubert 140241edb306SCy Schubert if (ipmonopts & IPMON_HEXHDR) { 140341edb306SCy Schubert dumphex(conf->log, ipmonopts, buf, 140441edb306SCy Schubert sizeof(iplog_t) + sizeof(*ipf)); 140541edb306SCy Schubert } 140641edb306SCy Schubert if (ipmonopts & IPMON_HEXBODY) { 140741edb306SCy Schubert dumphex(conf->log, ipmonopts, (char *)ip, 140841edb306SCy Schubert ipf->fl_plen + ipf->fl_hlen); 140941edb306SCy Schubert } else if ((ipmonopts & IPMON_LOGBODY) && 141041edb306SCy Schubert (ipf->fl_flags & FR_LOGBODY)) { 141141edb306SCy Schubert dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen, 141241edb306SCy Schubert ipf->fl_plen); 141341edb306SCy Schubert } 141441edb306SCy Schubert } 141541edb306SCy Schubert } 141641edb306SCy Schubert 141741edb306SCy Schubert 1418efeb8bffSCy Schubert static void 1419efeb8bffSCy Schubert usage(char *prog) 142041edb306SCy Schubert { 142141edb306SCy Schubert fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B <binary-logfile> ] [ -C <config-file> ]\n" 142241edb306SCy Schubert "\t[ -f <device> ] [ -L <facility> ] [ -N <device> ]\n" 142341edb306SCy Schubert "\t[ -o [NSI] ] [ -O [NSI] ] [ -P <pidfile> ] [ -S <device> ]\n" 142441edb306SCy Schubert "\t[ <filename> ]\n", prog); 142541edb306SCy Schubert exit(1); 142641edb306SCy Schubert } 142741edb306SCy Schubert 142841edb306SCy Schubert 1429efeb8bffSCy Schubert static void 1430efeb8bffSCy Schubert write_pid(char *file) 143141edb306SCy Schubert { 143241edb306SCy Schubert FILE *fp = NULL; 143341edb306SCy Schubert int fd; 143441edb306SCy Schubert 143541edb306SCy Schubert if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 143641edb306SCy Schubert fp = fdopen(fd, "w"); 143741edb306SCy Schubert if (fp == NULL) { 143841edb306SCy Schubert close(fd); 143941edb306SCy Schubert fprintf(stderr, 144041edb306SCy Schubert "unable to open/create pid file: %s\n", file); 144141edb306SCy Schubert return; 144241edb306SCy Schubert } 144341edb306SCy Schubert fprintf(fp, "%d", getpid()); 144441edb306SCy Schubert fclose(fp); 144541edb306SCy Schubert } 144641edb306SCy Schubert } 144741edb306SCy Schubert 144841edb306SCy Schubert 1449efeb8bffSCy Schubert static void 1450efeb8bffSCy Schubert flushlogs(char *file, FILE *log) 145141edb306SCy Schubert { 145241edb306SCy Schubert int fd, flushed = 0; 145341edb306SCy Schubert 145441edb306SCy Schubert if ((fd = open(file, O_RDWR)) == -1) { 145541edb306SCy Schubert (void) fprintf(stderr, "%s: open: %s\n", 145641edb306SCy Schubert file, STRERROR(errno)); 145741edb306SCy Schubert exit(1); 145841edb306SCy Schubert } 145941edb306SCy Schubert 146041edb306SCy Schubert if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 146141edb306SCy Schubert printf("%d bytes flushed from log buffer\n", 146241edb306SCy Schubert flushed); 146341edb306SCy Schubert fflush(stdout); 146441edb306SCy Schubert } else 146541edb306SCy Schubert ipferror(fd, "SIOCIPFFB"); 146641edb306SCy Schubert (void) close(fd); 146741edb306SCy Schubert 146841edb306SCy Schubert if (flushed) { 146941edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) { 147041edb306SCy Schubert syslog(LOG_INFO, "%d bytes flushed from log\n", 147141edb306SCy Schubert flushed); 147241edb306SCy Schubert } else if ((log != stdout) && (log != NULL)) { 147341edb306SCy Schubert fprintf(log, "%d bytes flushed from log\n", flushed); 147441edb306SCy Schubert } 147541edb306SCy Schubert } 147641edb306SCy Schubert } 147741edb306SCy Schubert 147841edb306SCy Schubert 1479efeb8bffSCy Schubert static void 1480efeb8bffSCy Schubert logopts(int turnon, char *options) 148141edb306SCy Schubert { 148241edb306SCy Schubert int flags = 0; 148341edb306SCy Schubert char *s; 148441edb306SCy Schubert 148541edb306SCy Schubert for (s = options; *s; s++) 148641edb306SCy Schubert { 148741edb306SCy Schubert switch (*s) 148841edb306SCy Schubert { 148941edb306SCy Schubert case 'N' : 149041edb306SCy Schubert flags |= IPMON_NAT; 149141edb306SCy Schubert break; 149241edb306SCy Schubert case 'S' : 149341edb306SCy Schubert flags |= IPMON_STATE; 149441edb306SCy Schubert break; 149541edb306SCy Schubert case 'I' : 149641edb306SCy Schubert flags |= IPMON_FILTER; 149741edb306SCy Schubert break; 149841edb306SCy Schubert default : 149941edb306SCy Schubert fprintf(stderr, "Unknown log option %c\n", *s); 150041edb306SCy Schubert exit(1); 150141edb306SCy Schubert } 150241edb306SCy Schubert } 150341edb306SCy Schubert 150441edb306SCy Schubert if (turnon) 150541edb306SCy Schubert ipmonopts |= flags; 150641edb306SCy Schubert else 150741edb306SCy Schubert ipmonopts &= ~(flags); 150841edb306SCy Schubert } 150941edb306SCy Schubert 1510efeb8bffSCy Schubert static void 1511efeb8bffSCy Schubert initconfig(config_t *conf) 151241edb306SCy Schubert { 151341edb306SCy Schubert int i; 151441edb306SCy Schubert 151541edb306SCy Schubert memset(conf, 0, sizeof(*conf)); 151641edb306SCy Schubert 151741edb306SCy Schubert conf->log = stdout; 151841edb306SCy Schubert conf->maxfd = -1; 151941edb306SCy Schubert 152041edb306SCy Schubert for (i = 0; i < 3; i++) { 152141edb306SCy Schubert conf->logsrc[i].fd = -1; 152241edb306SCy Schubert conf->logsrc[i].logtype = -1; 152341edb306SCy Schubert conf->logsrc[i].regular = -1; 152441edb306SCy Schubert } 152541edb306SCy Schubert 152641edb306SCy Schubert conf->logsrc[0].file = IPL_NAME; 152741edb306SCy Schubert conf->logsrc[1].file = IPNAT_NAME; 152841edb306SCy Schubert conf->logsrc[2].file = IPSTATE_NAME; 152941edb306SCy Schubert 153041edb306SCy Schubert add_doing(&executesaver); 153141edb306SCy Schubert add_doing(&snmpv1saver); 153241edb306SCy Schubert add_doing(&snmpv2saver); 153341edb306SCy Schubert add_doing(&syslogsaver); 153441edb306SCy Schubert add_doing(&filesaver); 153541edb306SCy Schubert add_doing(¬hingsaver); 153641edb306SCy Schubert } 153741edb306SCy Schubert 153841edb306SCy Schubert 1539efeb8bffSCy Schubert int 1540efeb8bffSCy Schubert main(int argc, char *argv[]) 154141edb306SCy Schubert { 154241edb306SCy Schubert int doread, c, make_daemon = 0; 154341edb306SCy Schubert char *prog; 154441edb306SCy Schubert config_t config; 154541edb306SCy Schubert 154641edb306SCy Schubert prog = strrchr(argv[0], '/'); 154741edb306SCy Schubert if (prog == NULL) 154841edb306SCy Schubert prog = argv[0]; 154941edb306SCy Schubert else 155041edb306SCy Schubert prog++; 155141edb306SCy Schubert 155241edb306SCy Schubert initconfig(&config); 155341edb306SCy Schubert 155441edb306SCy Schubert while ((c = getopt(argc, argv, 155541edb306SCy Schubert "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) 155641edb306SCy Schubert switch (c) 155741edb306SCy Schubert { 155841edb306SCy Schubert case 'a' : 155941edb306SCy Schubert ipmonopts |= IPMON_LOGALL; 156041edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 156141edb306SCy Schubert config.logsrc[1].logtype = IPL_LOGNAT; 156241edb306SCy Schubert config.logsrc[2].logtype = IPL_LOGSTATE; 156341edb306SCy Schubert break; 156441edb306SCy Schubert case 'b' : 156541edb306SCy Schubert ipmonopts |= IPMON_LOGBODY; 156641edb306SCy Schubert break; 156741edb306SCy Schubert case 'B' : 156841edb306SCy Schubert config.bfile = optarg; 156941edb306SCy Schubert config.blog = fopen(optarg, "a"); 157041edb306SCy Schubert break; 157141edb306SCy Schubert case 'C' : 157241edb306SCy Schubert config.cfile = optarg; 157341edb306SCy Schubert break; 157441edb306SCy Schubert case 'D' : 157541edb306SCy Schubert make_daemon = 1; 157641edb306SCy Schubert break; 157741edb306SCy Schubert case 'f' : case 'I' : 157841edb306SCy Schubert ipmonopts |= IPMON_FILTER; 157941edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 158041edb306SCy Schubert config.logsrc[0].file = optarg; 158141edb306SCy Schubert break; 158241edb306SCy Schubert case 'F' : 158341edb306SCy Schubert flushlogs(config.logsrc[0].file, config.log); 158441edb306SCy Schubert flushlogs(config.logsrc[1].file, config.log); 158541edb306SCy Schubert flushlogs(config.logsrc[2].file, config.log); 158641edb306SCy Schubert break; 158741edb306SCy Schubert case 'L' : 158841edb306SCy Schubert logfac = fac_findname(optarg); 158941edb306SCy Schubert if (logfac == -1) { 159041edb306SCy Schubert fprintf(stderr, 159141edb306SCy Schubert "Unknown syslog facility '%s'\n", 159241edb306SCy Schubert optarg); 159341edb306SCy Schubert exit(1); 159441edb306SCy Schubert } 159541edb306SCy Schubert break; 159641edb306SCy Schubert case 'n' : 159741edb306SCy Schubert ipmonopts |= IPMON_RESOLVE; 159841edb306SCy Schubert opts &= ~OPT_NORESOLVE; 159941edb306SCy Schubert break; 160041edb306SCy Schubert case 'N' : 160141edb306SCy Schubert ipmonopts |= IPMON_NAT; 160241edb306SCy Schubert config.logsrc[1].logtype = IPL_LOGNAT; 160341edb306SCy Schubert config.logsrc[1].file = optarg; 160441edb306SCy Schubert break; 160541edb306SCy Schubert case 'o' : case 'O' : 160641edb306SCy Schubert logopts(c == 'o', optarg); 160741edb306SCy Schubert if (ipmonopts & IPMON_FILTER) 160841edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 160941edb306SCy Schubert if (ipmonopts & IPMON_NAT) 161041edb306SCy Schubert config.logsrc[1].logtype = IPL_LOGNAT; 161141edb306SCy Schubert if (ipmonopts & IPMON_STATE) 161241edb306SCy Schubert config.logsrc[2].logtype = IPL_LOGSTATE; 161341edb306SCy Schubert break; 161441edb306SCy Schubert case 'p' : 161541edb306SCy Schubert ipmonopts |= IPMON_PORTNUM; 161641edb306SCy Schubert break; 161741edb306SCy Schubert case 'P' : 161841edb306SCy Schubert pidfile = optarg; 161941edb306SCy Schubert break; 162041edb306SCy Schubert case 's' : 162141edb306SCy Schubert ipmonopts |= IPMON_SYSLOG; 162241edb306SCy Schubert config.log = NULL; 162341edb306SCy Schubert break; 162441edb306SCy Schubert case 'S' : 162541edb306SCy Schubert ipmonopts |= IPMON_STATE; 162641edb306SCy Schubert config.logsrc[2].logtype = IPL_LOGSTATE; 162741edb306SCy Schubert config.logsrc[2].file = optarg; 162841edb306SCy Schubert break; 162941edb306SCy Schubert case 't' : 163041edb306SCy Schubert ipmonopts |= IPMON_TAIL; 163141edb306SCy Schubert break; 163241edb306SCy Schubert case 'v' : 163341edb306SCy Schubert ipmonopts |= IPMON_VERBOSE; 163441edb306SCy Schubert break; 163541edb306SCy Schubert case 'x' : 163641edb306SCy Schubert ipmonopts |= IPMON_HEXBODY; 163741edb306SCy Schubert break; 163841edb306SCy Schubert case 'X' : 163941edb306SCy Schubert ipmonopts |= IPMON_HEXHDR; 164041edb306SCy Schubert break; 164141edb306SCy Schubert default : 164241edb306SCy Schubert case 'h' : 164341edb306SCy Schubert case '?' : 164441edb306SCy Schubert usage(argv[0]); 164541edb306SCy Schubert } 164641edb306SCy Schubert 164741edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 164841edb306SCy Schubert openlog(prog, LOG_NDELAY|LOG_PID, logfac); 164941edb306SCy Schubert 165041edb306SCy Schubert init_tabs(); 165141edb306SCy Schubert if (config.cfile) 165241edb306SCy Schubert if (load_config(config.cfile) == -1) { 165341edb306SCy Schubert unload_config(); 165441edb306SCy Schubert exit(1); 165541edb306SCy Schubert } 165641edb306SCy Schubert 165741edb306SCy Schubert /* 165841edb306SCy Schubert * Default action is to only open the filter log file. 165941edb306SCy Schubert */ 166041edb306SCy Schubert if ((config.logsrc[0].logtype == -1) && 166141edb306SCy Schubert (config.logsrc[0].logtype == -1) && 166241edb306SCy Schubert (config.logsrc[0].logtype == -1)) 166341edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 166441edb306SCy Schubert 166541edb306SCy Schubert openlogs(&config); 166641edb306SCy Schubert 166741edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 166841edb306SCy Schubert config.file = argv[optind]; 166941edb306SCy Schubert config.log = config.file ? fopen(config.file, "a") : stdout; 167041edb306SCy Schubert if (config.log == NULL) { 167141edb306SCy Schubert (void) fprintf(stderr, "%s: fopen: %s\n", 167241edb306SCy Schubert argv[optind], STRERROR(errno)); 167341edb306SCy Schubert exit(1); 167441edb306SCy Schubert /* NOTREACHED */ 167541edb306SCy Schubert } 167641edb306SCy Schubert setvbuf(config.log, NULL, _IONBF, 0); 167741edb306SCy Schubert } else { 167841edb306SCy Schubert config.log = NULL; 167941edb306SCy Schubert } 168041edb306SCy Schubert 168141edb306SCy Schubert if (make_daemon && 168241edb306SCy Schubert ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { 168341edb306SCy Schubert #ifdef BSD 168441edb306SCy Schubert daemon(0, !(ipmonopts & IPMON_SYSLOG)); 168541edb306SCy Schubert #else 168641edb306SCy Schubert int pid; 168741edb306SCy Schubert 168841edb306SCy Schubert switch (fork()) 168941edb306SCy Schubert { 169041edb306SCy Schubert case -1 : 169141edb306SCy Schubert (void) fprintf(stderr, "%s: fork() failed: %s\n", 169241edb306SCy Schubert argv[0], STRERROR(errno)); 169341edb306SCy Schubert exit(1); 169441edb306SCy Schubert /* NOTREACHED */ 169541edb306SCy Schubert case 0 : 169641edb306SCy Schubert break; 169741edb306SCy Schubert default : 169841edb306SCy Schubert exit(0); 169941edb306SCy Schubert } 170041edb306SCy Schubert 170141edb306SCy Schubert setsid(); 170241edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG)) 170341edb306SCy Schubert close(2); 170441edb306SCy Schubert #endif /* !BSD */ 170541edb306SCy Schubert close(0); 170641edb306SCy Schubert close(1); 170741edb306SCy Schubert write_pid(pidfile); 170841edb306SCy Schubert } 170941edb306SCy Schubert 171041edb306SCy Schubert signal(SIGHUP, handlehup); 171141edb306SCy Schubert 171241edb306SCy Schubert for (doread = 1; doread; ) 171341edb306SCy Schubert doread = read_loginfo(&config); 171441edb306SCy Schubert 171541edb306SCy Schubert unload_config(); 171641edb306SCy Schubert 171741edb306SCy Schubert return (0); 171841edb306SCy Schubert /* NOTREACHED */ 171941edb306SCy Schubert } 172041edb306SCy Schubert 172141edb306SCy Schubert 1722efeb8bffSCy Schubert static void 1723efeb8bffSCy Schubert openlogs(config_t *conf) 172441edb306SCy Schubert { 172541edb306SCy Schubert logsource_t *l; 172641edb306SCy Schubert struct stat sb; 172741edb306SCy Schubert int i; 172841edb306SCy Schubert 172941edb306SCy Schubert for (i = 0; i < 3; i++) { 173041edb306SCy Schubert l = &conf->logsrc[i]; 173141edb306SCy Schubert if (l->logtype == -1) 173241edb306SCy Schubert continue; 173341edb306SCy Schubert if (!strcmp(l->file, "-")) 173441edb306SCy Schubert l->fd = 0; 173541edb306SCy Schubert else { 173641edb306SCy Schubert if ((l->fd= open(l->file, O_RDONLY)) == -1) { 173741edb306SCy Schubert (void) fprintf(stderr, 173841edb306SCy Schubert "%s: open: %s\n", l->file, 173941edb306SCy Schubert STRERROR(errno)); 174041edb306SCy Schubert exit(1); 174141edb306SCy Schubert /* NOTREACHED */ 174241edb306SCy Schubert } 174341edb306SCy Schubert 174441edb306SCy Schubert if (fstat(l->fd, &sb) == -1) { 174541edb306SCy Schubert (void) fprintf(stderr, "%d: fstat: %s\n", 174641edb306SCy Schubert l->fd, STRERROR(errno)); 174741edb306SCy Schubert exit(1); 174841edb306SCy Schubert /* NOTREACHED */ 174941edb306SCy Schubert } 175041edb306SCy Schubert 175141edb306SCy Schubert l->regular = !S_ISCHR(sb.st_mode); 175241edb306SCy Schubert if (l->regular) 175341edb306SCy Schubert l->size = sb.st_size; 175441edb306SCy Schubert 175541edb306SCy Schubert FD_SET(l->fd, &conf->fdmr); 175641edb306SCy Schubert if (l->fd > conf->maxfd) 175741edb306SCy Schubert conf->maxfd = l->fd; 175841edb306SCy Schubert } 175941edb306SCy Schubert } 176041edb306SCy Schubert } 176141edb306SCy Schubert 176241edb306SCy Schubert 1763efeb8bffSCy Schubert static int 1764efeb8bffSCy Schubert read_loginfo(config_t *conf) 176541edb306SCy Schubert { 176641edb306SCy Schubert iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1]; 176741edb306SCy Schubert int n, tr, nr, i; 176841edb306SCy Schubert logsource_t *l; 176941edb306SCy Schubert fd_set fdr; 177041edb306SCy Schubert 177141edb306SCy Schubert fdr = conf->fdmr; 177241edb306SCy Schubert 177341edb306SCy Schubert n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL); 177441edb306SCy Schubert if (n == 0) 17752582ae57SCy Schubert return (1); 177641edb306SCy Schubert if (n == -1) { 177741edb306SCy Schubert if (errno == EINTR) 17782582ae57SCy Schubert return (1); 17792582ae57SCy Schubert return (-1); 178041edb306SCy Schubert } 178141edb306SCy Schubert 178241edb306SCy Schubert for (i = 0, nr = 0; i < 3; i++) { 178341edb306SCy Schubert l = &conf->logsrc[i]; 178441edb306SCy Schubert 178541edb306SCy Schubert if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr)) 178641edb306SCy Schubert continue; 178741edb306SCy Schubert 178841edb306SCy Schubert tr = 0; 178941edb306SCy Schubert if (l->regular) { 179041edb306SCy Schubert tr = (lseek(l->fd, 0, SEEK_CUR) < l->size); 179141edb306SCy Schubert if (!tr && !(ipmonopts & IPMON_TAIL)) 17922582ae57SCy Schubert return (0); 179341edb306SCy Schubert } 179441edb306SCy Schubert 179541edb306SCy Schubert n = 0; 179641edb306SCy Schubert tr = read_log(l->fd, &n, (char *)buf, sizeof(buf)); 179741edb306SCy Schubert if (donehup) { 179841edb306SCy Schubert if (conf->file != NULL) { 179941edb306SCy Schubert if (conf->log != NULL) { 180041edb306SCy Schubert fclose(conf->log); 180141edb306SCy Schubert conf->log = NULL; 180241edb306SCy Schubert } 180341edb306SCy Schubert conf->log = fopen(conf->file, "a"); 180441edb306SCy Schubert } 180541edb306SCy Schubert 180641edb306SCy Schubert if (conf->bfile != NULL) { 180741edb306SCy Schubert if (conf->blog != NULL) { 180841edb306SCy Schubert fclose(conf->blog); 180941edb306SCy Schubert conf->blog = NULL; 181041edb306SCy Schubert } 181141edb306SCy Schubert conf->blog = fopen(conf->bfile, "a"); 181241edb306SCy Schubert } 181341edb306SCy Schubert 181441edb306SCy Schubert init_tabs(); 181541edb306SCy Schubert if (conf->cfile != NULL) 181641edb306SCy Schubert load_config(conf->cfile); 181741edb306SCy Schubert donehup = 0; 181841edb306SCy Schubert } 181941edb306SCy Schubert 182041edb306SCy Schubert switch (tr) 182141edb306SCy Schubert { 182241edb306SCy Schubert case -1 : 182341edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 182441edb306SCy Schubert syslog(LOG_CRIT, "read: %m\n"); 182541edb306SCy Schubert else { 182641edb306SCy Schubert ipferror(l->fd, "read"); 182741edb306SCy Schubert } 18282582ae57SCy Schubert return (0); 182941edb306SCy Schubert case 1 : 183041edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 183141edb306SCy Schubert syslog(LOG_CRIT, "aborting logging\n"); 183241edb306SCy Schubert else if (conf->log != NULL) 183341edb306SCy Schubert fprintf(conf->log, "aborting logging\n"); 18342582ae57SCy Schubert return (0); 183541edb306SCy Schubert case 2 : 183641edb306SCy Schubert break; 183741edb306SCy Schubert case 0 : 183841edb306SCy Schubert nr += tr; 183941edb306SCy Schubert if (n > 0) { 184041edb306SCy Schubert print_log(conf, l, (char *)buf, n); 184141edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) 184241edb306SCy Schubert fflush(conf->log); 184341edb306SCy Schubert } 184441edb306SCy Schubert break; 184541edb306SCy Schubert } 184641edb306SCy Schubert } 184741edb306SCy Schubert 184841edb306SCy Schubert if (!nr && (ipmonopts & IPMON_TAIL)) 184941edb306SCy Schubert sleep(1); 185041edb306SCy Schubert 18512582ae57SCy Schubert return (1); 185241edb306SCy Schubert } 1853