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 30841edb306SCy Schubert if (tablesz < 2) 3092582ae57SCy Schubert return (NULL); 31041edb306SCy Schubert 31141edb306SCy Schubert if ((type < 0) || (type > table[tablesz - 2].ist_val)) 3122582ae57SCy Schubert return (NULL); 31341edb306SCy Schubert 31441edb306SCy Schubert if (table[type].ist_val == type) 3152582ae57SCy Schubert return (table + type); 31641edb306SCy Schubert 317*90f2fee0SJohn Baldwin for (ist = table; ist->ist_val != -2; ist++) 31841edb306SCy Schubert if (ist->ist_val == type) 3192582ae57SCy Schubert return (ist); 3202582ae57SCy Schubert return (NULL); 32141edb306SCy Schubert } 32241edb306SCy Schubert 32341edb306SCy Schubert 324efeb8bffSCy Schubert static icmp_type_t * 325efeb8bffSCy Schubert find_icmptype(int type, icmp_type_t *table, size_t tablesz) 32641edb306SCy Schubert { 32741edb306SCy Schubert icmp_type_t *it; 32841edb306SCy Schubert 32941edb306SCy Schubert if (tablesz < 2) 3302582ae57SCy Schubert return (NULL); 33141edb306SCy Schubert 33241edb306SCy Schubert if ((type < 0) || (type > table[tablesz - 2].it_val)) 3332582ae57SCy Schubert return (NULL); 33441edb306SCy Schubert 33541edb306SCy Schubert if (table[type].it_val == type) 3362582ae57SCy Schubert return (table + type); 33741edb306SCy Schubert 338*90f2fee0SJohn Baldwin for (it = table; it->it_val != -2; it++) 33941edb306SCy Schubert if (it->it_val == type) 3402582ae57SCy Schubert return (it); 3412582ae57SCy Schubert return (NULL); 34241edb306SCy Schubert } 34341edb306SCy Schubert 34441edb306SCy Schubert 345efeb8bffSCy Schubert static void 346efeb8bffSCy Schubert handlehup(int sig) 34741edb306SCy Schubert { 34841edb306SCy Schubert signal(SIGHUP, handlehup); 34941edb306SCy Schubert donehup = 1; 35041edb306SCy Schubert } 35141edb306SCy Schubert 35241edb306SCy Schubert 353efeb8bffSCy Schubert static void 354efeb8bffSCy Schubert init_tabs(void) 35541edb306SCy Schubert { 35641edb306SCy Schubert struct protoent *p; 35741edb306SCy Schubert struct servent *s; 35841edb306SCy Schubert char *name, **tab; 35941edb306SCy Schubert int port, i; 36041edb306SCy Schubert 36141edb306SCy Schubert if (protocols != NULL) { 36241edb306SCy Schubert for (i = 0; i < 256; i++) 36341edb306SCy Schubert if (protocols[i] != NULL) { 36441edb306SCy Schubert free(protocols[i]); 36541edb306SCy Schubert protocols[i] = NULL; 36641edb306SCy Schubert } 36741edb306SCy Schubert free(protocols); 36841edb306SCy Schubert protocols = NULL; 36941edb306SCy Schubert } 37041edb306SCy Schubert protocols = (char **)malloc(256 * sizeof(*protocols)); 37141edb306SCy Schubert if (protocols != NULL) { 37241edb306SCy Schubert bzero((char *)protocols, 256 * sizeof(*protocols)); 37341edb306SCy Schubert 37441edb306SCy Schubert setprotoent(1); 37541edb306SCy Schubert while ((p = getprotoent()) != NULL) 37641edb306SCy Schubert if (p->p_proto >= 0 && p->p_proto <= 255 && 37741edb306SCy Schubert p->p_name != NULL && protocols[p->p_proto] == NULL) 37841edb306SCy Schubert protocols[p->p_proto] = strdup(p->p_name); 37941edb306SCy Schubert endprotoent(); 38041edb306SCy Schubert if (protocols[0]) 38141edb306SCy Schubert free(protocols[0]); 38241edb306SCy Schubert protocols[0] = strdup("ip"); 38341edb306SCy Schubert } 38441edb306SCy Schubert 38541edb306SCy Schubert if (udp_ports != NULL) { 38641edb306SCy Schubert for (i = 0; i < 65536; i++) 38741edb306SCy Schubert if (udp_ports[i] != NULL) { 38841edb306SCy Schubert free(udp_ports[i]); 38941edb306SCy Schubert udp_ports[i] = NULL; 39041edb306SCy Schubert } 39141edb306SCy Schubert free(udp_ports); 39241edb306SCy Schubert udp_ports = NULL; 39341edb306SCy Schubert } 39441edb306SCy Schubert udp_ports = (char **)malloc(65536 * sizeof(*udp_ports)); 39541edb306SCy Schubert if (udp_ports != NULL) 39641edb306SCy Schubert bzero((char *)udp_ports, 65536 * sizeof(*udp_ports)); 39741edb306SCy Schubert 39841edb306SCy Schubert if (tcp_ports != NULL) { 39941edb306SCy Schubert for (i = 0; i < 65536; i++) 40041edb306SCy Schubert if (tcp_ports[i] != NULL) { 40141edb306SCy Schubert free(tcp_ports[i]); 40241edb306SCy Schubert tcp_ports[i] = NULL; 40341edb306SCy Schubert } 40441edb306SCy Schubert free(tcp_ports); 40541edb306SCy Schubert tcp_ports = NULL; 40641edb306SCy Schubert } 40741edb306SCy Schubert tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports)); 40841edb306SCy Schubert if (tcp_ports != NULL) 40941edb306SCy Schubert bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports)); 41041edb306SCy Schubert 41141edb306SCy Schubert setservent(1); 41241edb306SCy Schubert while ((s = getservent()) != NULL) { 41341edb306SCy Schubert if (s->s_proto == NULL) 41441edb306SCy Schubert continue; 41541edb306SCy Schubert else if (!strcmp(s->s_proto, "tcp")) { 41641edb306SCy Schubert port = ntohs(s->s_port); 41741edb306SCy Schubert name = s->s_name; 41841edb306SCy Schubert tab = tcp_ports; 41941edb306SCy Schubert } else if (!strcmp(s->s_proto, "udp")) { 42041edb306SCy Schubert port = ntohs(s->s_port); 42141edb306SCy Schubert name = s->s_name; 42241edb306SCy Schubert tab = udp_ports; 42341edb306SCy Schubert } else 42441edb306SCy Schubert continue; 42541edb306SCy Schubert if ((port < 0 || port > 65535) || (name == NULL)) 42641edb306SCy Schubert continue; 42741edb306SCy Schubert if (tab != NULL) 42841edb306SCy Schubert tab[port] = strdup(name); 42941edb306SCy Schubert } 43041edb306SCy Schubert endservent(); 43141edb306SCy Schubert } 43241edb306SCy Schubert 43341edb306SCy Schubert 434efeb8bffSCy Schubert static char * 435efeb8bffSCy Schubert getlocalproto(u_int p) 43641edb306SCy Schubert { 43741edb306SCy Schubert static char pnum[4]; 43841edb306SCy Schubert char *s; 43941edb306SCy Schubert 44041edb306SCy Schubert p &= 0xff; 44141edb306SCy Schubert s = protocols ? protocols[p] : NULL; 44241edb306SCy Schubert if (s == NULL) { 443d740faa3SCy Schubert sprintf(pnum, "%u", p); 44441edb306SCy Schubert s = pnum; 44541edb306SCy Schubert } 4462582ae57SCy Schubert return (s); 44741edb306SCy Schubert } 44841edb306SCy Schubert 44941edb306SCy Schubert 450efeb8bffSCy Schubert static int 451efeb8bffSCy Schubert read_log(int fd, int *lenp, char *buf, int bufsize) 45241edb306SCy Schubert { 45341edb306SCy Schubert int nr; 45441edb306SCy Schubert 45541edb306SCy Schubert if (bufsize > IPFILTER_LOGSIZE) 45641edb306SCy Schubert bufsize = IPFILTER_LOGSIZE; 45741edb306SCy Schubert 45841edb306SCy Schubert nr = read(fd, buf, bufsize); 45941edb306SCy Schubert if (!nr) 4602582ae57SCy Schubert return (2); 46141edb306SCy Schubert if ((nr < 0) && (errno != EINTR)) 4622582ae57SCy Schubert return (-1); 46341edb306SCy Schubert *lenp = nr; 4642582ae57SCy Schubert return (0); 46541edb306SCy Schubert } 46641edb306SCy Schubert 46741edb306SCy Schubert 468efeb8bffSCy Schubert char * 4692ac057ddSJohn Baldwin portlocalname(int res, char *proto, u_int port) 47041edb306SCy Schubert { 47141edb306SCy Schubert static char pname[8]; 47241edb306SCy Schubert char *s; 47341edb306SCy Schubert 47441edb306SCy Schubert port = ntohs(port); 47541edb306SCy Schubert port &= 0xffff; 476d740faa3SCy Schubert sprintf(pname, "%u", port); 47741edb306SCy Schubert if (!res || (ipmonopts & IPMON_PORTNUM)) 4782582ae57SCy Schubert return (pname); 47941edb306SCy Schubert s = NULL; 48041edb306SCy Schubert if (!strcmp(proto, "tcp")) 48141edb306SCy Schubert s = tcp_ports[port]; 48241edb306SCy Schubert else if (!strcmp(proto, "udp")) 48341edb306SCy Schubert s = udp_ports[port]; 48441edb306SCy Schubert if (s == NULL) 48541edb306SCy Schubert s = pname; 4862582ae57SCy Schubert return (s); 48741edb306SCy Schubert } 48841edb306SCy Schubert 48941edb306SCy Schubert 490efeb8bffSCy Schubert static char * 491efeb8bffSCy Schubert icmpname(u_int type, u_int code) 49241edb306SCy Schubert { 49341edb306SCy Schubert static char name[80]; 49441edb306SCy Schubert icmp_subtype_t *ist; 49541edb306SCy Schubert icmp_type_t *it; 49641edb306SCy Schubert char *s; 49741edb306SCy Schubert 49841edb306SCy Schubert s = NULL; 49941edb306SCy Schubert it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it)); 50041edb306SCy Schubert if (it != NULL) 50141edb306SCy Schubert s = it->it_name; 50241edb306SCy Schubert 50341edb306SCy Schubert if (s == NULL) 504d740faa3SCy Schubert sprintf(name, "icmptype(%d)/", type); 50541edb306SCy Schubert else 506d740faa3SCy Schubert sprintf(name, "%s/", s); 50741edb306SCy Schubert 50841edb306SCy Schubert ist = NULL; 50941edb306SCy Schubert if (it != NULL && it->it_subtable != NULL) 51041edb306SCy Schubert ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 51141edb306SCy Schubert 51241edb306SCy Schubert if (ist != NULL && ist->ist_name != NULL) 51341edb306SCy Schubert strcat(name, ist->ist_name); 514d740faa3SCy Schubert else 515d740faa3SCy Schubert sprintf(name + strlen(name), "%d", code); 51641edb306SCy Schubert 5172582ae57SCy Schubert return (name); 51841edb306SCy Schubert } 51941edb306SCy Schubert 520efeb8bffSCy Schubert static char * 521efeb8bffSCy Schubert icmpname6(u_int type, u_int code) 52241edb306SCy Schubert { 52341edb306SCy Schubert static char name[80]; 52441edb306SCy Schubert icmp_subtype_t *ist; 52541edb306SCy Schubert icmp_type_t *it; 52641edb306SCy Schubert char *s; 52741edb306SCy Schubert 52841edb306SCy Schubert s = NULL; 52941edb306SCy Schubert it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it)); 53041edb306SCy Schubert if (it != NULL) 53141edb306SCy Schubert s = it->it_name; 53241edb306SCy Schubert 53341edb306SCy Schubert if (s == NULL) 534d740faa3SCy Schubert sprintf(name, "icmpv6type(%d)/", type); 53541edb306SCy Schubert else 536d740faa3SCy Schubert sprintf(name, "%s/", s); 53741edb306SCy Schubert 53841edb306SCy Schubert ist = NULL; 53941edb306SCy Schubert if (it != NULL && it->it_subtable != NULL) 54041edb306SCy Schubert ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize); 54141edb306SCy Schubert 54241edb306SCy Schubert if (ist != NULL && ist->ist_name != NULL) 54341edb306SCy Schubert strcat(name, ist->ist_name); 544d740faa3SCy Schubert else 545d740faa3SCy Schubert sprintf(name + strlen(name), "%d", code); 54641edb306SCy Schubert 5472582ae57SCy Schubert return (name); 54841edb306SCy Schubert } 54941edb306SCy Schubert 55041edb306SCy Schubert 551efeb8bffSCy Schubert void 552efeb8bffSCy Schubert dumphex(FILE *log, int dopts, char *buf, int len) 55341edb306SCy Schubert { 55441edb306SCy Schubert char hline[80]; 55541edb306SCy Schubert int i, j, k; 55641edb306SCy Schubert u_char *s = (u_char *)buf, *t = (u_char *)hline; 55741edb306SCy Schubert 55841edb306SCy Schubert if (buf == NULL || len == 0) 55941edb306SCy Schubert return; 56041edb306SCy Schubert 56141edb306SCy Schubert *hline = '\0'; 56241edb306SCy Schubert 56341edb306SCy Schubert for (i = len, j = 0; i; i--, j++, s++) { 56441edb306SCy Schubert if (j && !(j & 0xf)) { 56541edb306SCy Schubert *t++ = '\n'; 56641edb306SCy Schubert *t = '\0'; 56741edb306SCy Schubert if ((dopts & IPMON_SYSLOG)) 56841edb306SCy Schubert syslog(LOG_INFO, "%s", hline); 56941edb306SCy Schubert else if (log != NULL) 57041edb306SCy Schubert fputs(hline, log); 57141edb306SCy Schubert t = (u_char *)hline; 57241edb306SCy Schubert *t = '\0'; 57341edb306SCy Schubert } 57441edb306SCy Schubert sprintf((char *)t, "%02x", *s & 0xff); 57541edb306SCy Schubert t += 2; 57641edb306SCy Schubert if (!((j + 1) & 0xf)) { 57741edb306SCy Schubert s -= 15; 57841edb306SCy Schubert sprintf((char *)t, " "); 57941edb306SCy Schubert t += 8; 58041edb306SCy Schubert for (k = 16; k; k--, s++) 58141edb306SCy Schubert *t++ = (isprint(*s) ? *s : '.'); 58241edb306SCy Schubert s--; 58341edb306SCy Schubert } 58441edb306SCy Schubert 58541edb306SCy Schubert if ((j + 1) & 0xf) 58641edb306SCy Schubert *t++ = ' ';; 58741edb306SCy Schubert } 58841edb306SCy Schubert 58941edb306SCy Schubert if (j & 0xf) { 59041edb306SCy Schubert for (k = 16 - (j & 0xf); k; k--) { 59141edb306SCy Schubert *t++ = ' '; 59241edb306SCy Schubert *t++ = ' '; 59341edb306SCy Schubert *t++ = ' '; 59441edb306SCy Schubert } 59541edb306SCy Schubert sprintf((char *)t, " "); 59641edb306SCy Schubert t += 7; 59741edb306SCy Schubert s -= j & 0xf; 59841edb306SCy Schubert for (k = j & 0xf; k; k--, s++) 59941edb306SCy Schubert *t++ = (isprint(*s) ? *s : '.'); 60041edb306SCy Schubert *t++ = '\n'; 60141edb306SCy Schubert *t = '\0'; 60241edb306SCy Schubert } 60341edb306SCy Schubert if ((dopts & IPMON_SYSLOG) != 0) 60441edb306SCy Schubert syslog(LOG_INFO, "%s", hline); 60541edb306SCy Schubert else if (log != NULL) { 60641edb306SCy Schubert fputs(hline, log); 60741edb306SCy Schubert fflush(log); 60841edb306SCy Schubert } 60941edb306SCy Schubert } 61041edb306SCy Schubert 61141edb306SCy Schubert 612efeb8bffSCy Schubert static struct tm * 613efeb8bffSCy Schubert get_tm(time_t sec) 61441edb306SCy Schubert { 61541edb306SCy Schubert struct tm *tm; 61641edb306SCy Schubert time_t t; 61741edb306SCy Schubert 61841edb306SCy Schubert t = sec; 61941edb306SCy Schubert tm = localtime(&t); 6202582ae57SCy Schubert return (tm); 62141edb306SCy Schubert } 62241edb306SCy Schubert 623efeb8bffSCy Schubert static void 624efeb8bffSCy Schubert print_natlog(config_t *conf, char *buf, int blen) 62541edb306SCy Schubert { 62641edb306SCy Schubert static u_32_t seqnum = 0; 62741edb306SCy Schubert int res, i, len, family; 62841edb306SCy Schubert struct natlog *nl; 62941edb306SCy Schubert struct tm *tm; 63041edb306SCy Schubert iplog_t *ipl; 63141edb306SCy Schubert char *proto; 63241edb306SCy Schubert int simple; 63341edb306SCy Schubert char *t; 63441edb306SCy Schubert 63541edb306SCy Schubert t = line; 63641edb306SCy Schubert simple = 0; 63741edb306SCy Schubert ipl = (iplog_t *)buf; 63841edb306SCy Schubert if (ipl->ipl_seqnum != seqnum) { 63941edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG) != 0) { 64041edb306SCy Schubert syslog(LOG_WARNING, 64141edb306SCy Schubert "missed %u NAT log entries: %u %u", 64241edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 64341edb306SCy Schubert ipl->ipl_seqnum); 64441edb306SCy Schubert } else { 64541edb306SCy Schubert (void) fprintf(conf->log, 64641edb306SCy Schubert "missed %u NAT log entries: %u %u\n", 64741edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 64841edb306SCy Schubert ipl->ipl_seqnum); 64941edb306SCy Schubert } 65041edb306SCy Schubert } 65141edb306SCy Schubert seqnum = ipl->ipl_seqnum + ipl->ipl_count; 65241edb306SCy Schubert 65341edb306SCy Schubert nl = (struct natlog *)((char *)ipl + sizeof(*ipl)); 65441edb306SCy Schubert res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 65541edb306SCy Schubert tm = get_tm(ipl->ipl_sec); 65641edb306SCy Schubert len = sizeof(line); 65741edb306SCy Schubert 65841edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 65941edb306SCy Schubert (void) strftime(t, len, "%d/%m/%Y ", tm); 66041edb306SCy Schubert i = strlen(t); 66141edb306SCy Schubert len -= i; 66241edb306SCy Schubert t += i; 66341edb306SCy Schubert } 66441edb306SCy Schubert (void) strftime(t, len, "%T", tm); 66541edb306SCy Schubert t += strlen(t); 666d740faa3SCy Schubert sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1); 66741edb306SCy Schubert t += strlen(t); 66841edb306SCy Schubert 66941edb306SCy Schubert switch (nl->nl_action) 67041edb306SCy Schubert { 67141edb306SCy Schubert case NL_NEW : 67241edb306SCy Schubert strcpy(t, "NAT:NEW"); 67341edb306SCy Schubert break; 67441edb306SCy Schubert 67541edb306SCy Schubert case NL_FLUSH : 67641edb306SCy Schubert strcpy(t, "NAT:FLUSH"); 67741edb306SCy Schubert break; 67841edb306SCy Schubert 67941edb306SCy Schubert case NL_CLONE : 68041edb306SCy Schubert strcpy(t, "NAT:CLONE"); 68141edb306SCy Schubert break; 68241edb306SCy Schubert 68341edb306SCy Schubert case NL_EXPIRE : 68441edb306SCy Schubert strcpy(t, "NAT:EXPIRE"); 68541edb306SCy Schubert break; 68641edb306SCy Schubert 68741edb306SCy Schubert case NL_DESTROY : 68841edb306SCy Schubert strcpy(t, "NAT:DESTROY"); 68941edb306SCy Schubert break; 69041edb306SCy Schubert 69141edb306SCy Schubert case NL_PURGE : 69241edb306SCy Schubert strcpy(t, "NAT:PURGE"); 69341edb306SCy Schubert break; 69441edb306SCy Schubert 69541edb306SCy Schubert default : 696d740faa3SCy Schubert sprintf(t, "NAT:Action(%d)", nl->nl_action); 69741edb306SCy Schubert break; 69841edb306SCy Schubert } 69941edb306SCy Schubert t += strlen(t); 70041edb306SCy Schubert 70141edb306SCy Schubert 70241edb306SCy Schubert switch (nl->nl_type) 70341edb306SCy Schubert { 70441edb306SCy Schubert case NAT_MAP : 70541edb306SCy Schubert strcpy(t, "-MAP "); 70641edb306SCy Schubert simple = 1; 70741edb306SCy Schubert break; 70841edb306SCy Schubert 70941edb306SCy Schubert case NAT_REDIRECT : 71041edb306SCy Schubert strcpy(t, "-RDR "); 71141edb306SCy Schubert simple = 1; 71241edb306SCy Schubert break; 71341edb306SCy Schubert 71441edb306SCy Schubert case NAT_BIMAP : 71541edb306SCy Schubert strcpy(t, "-BIMAP "); 71641edb306SCy Schubert simple = 1; 71741edb306SCy Schubert break; 71841edb306SCy Schubert 71941edb306SCy Schubert case NAT_MAPBLK : 72041edb306SCy Schubert strcpy(t, "-MAPBLOCK "); 72141edb306SCy Schubert simple = 1; 72241edb306SCy Schubert break; 72341edb306SCy Schubert 72441edb306SCy Schubert case NAT_REWRITE|NAT_MAP : 72541edb306SCy Schubert strcpy(t, "-RWR_MAP "); 72641edb306SCy Schubert break; 72741edb306SCy Schubert 72841edb306SCy Schubert case NAT_REWRITE|NAT_REDIRECT : 72941edb306SCy Schubert strcpy(t, "-RWR_RDR "); 73041edb306SCy Schubert break; 73141edb306SCy Schubert 73241edb306SCy Schubert case NAT_ENCAP|NAT_MAP : 73341edb306SCy Schubert strcpy(t, "-ENC_MAP "); 73441edb306SCy Schubert break; 73541edb306SCy Schubert 73641edb306SCy Schubert case NAT_ENCAP|NAT_REDIRECT : 73741edb306SCy Schubert strcpy(t, "-ENC_RDR "); 73841edb306SCy Schubert break; 73941edb306SCy Schubert 74041edb306SCy Schubert case NAT_DIVERTUDP|NAT_MAP : 74141edb306SCy Schubert strcpy(t, "-DIV_MAP "); 74241edb306SCy Schubert break; 74341edb306SCy Schubert 74441edb306SCy Schubert case NAT_DIVERTUDP|NAT_REDIRECT : 74541edb306SCy Schubert strcpy(t, "-DIV_RDR "); 74641edb306SCy Schubert break; 74741edb306SCy Schubert 74841edb306SCy Schubert default : 749d740faa3SCy Schubert sprintf(t, "-Type(%d) ", nl->nl_type); 75041edb306SCy Schubert break; 75141edb306SCy Schubert } 75241edb306SCy Schubert t += strlen(t); 75341edb306SCy Schubert 75441edb306SCy Schubert proto = getlocalproto(nl->nl_p[0]); 75541edb306SCy Schubert 75641edb306SCy Schubert family = vtof(nl->nl_v[0]); 75741edb306SCy Schubert 75841edb306SCy Schubert if (simple == 1) { 759d740faa3SCy Schubert sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6), 76041edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_osrcport)); 76141edb306SCy Schubert t += strlen(t); 762d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 76341edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 76441edb306SCy Schubert t += strlen(t); 765d740faa3SCy Schubert sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6), 76641edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_odstport)); 76741edb306SCy Schubert } else { 768d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6), 76941edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_osrcport)); 77041edb306SCy Schubert t += strlen(t); 771d740faa3SCy Schubert sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6), 77241edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_odstport)); 77341edb306SCy Schubert t += strlen(t); 774d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6), 77541edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_nsrcport)); 77641edb306SCy Schubert t += strlen(t); 777d740faa3SCy Schubert sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6), 77841edb306SCy Schubert portlocalname(res, proto, (u_int)nl->nl_ndstport)); 77941edb306SCy Schubert } 78041edb306SCy Schubert t += strlen(t); 78141edb306SCy Schubert 78241edb306SCy Schubert strcpy(t, getlocalproto(nl->nl_p[0])); 78341edb306SCy Schubert t += strlen(t); 78441edb306SCy Schubert 78541edb306SCy Schubert if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) { 78641edb306SCy Schubert #ifdef USE_QUAD_T 78741edb306SCy Schubert # ifdef PRId64 788d740faa3SCy Schubert sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%" 78941edb306SCy Schubert PRId64, 79041edb306SCy Schubert # else 791d740faa3SCy Schubert sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd", 79241edb306SCy Schubert # endif 79341edb306SCy Schubert #else 794d740faa3SCy Schubert sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld", 79541edb306SCy Schubert #endif 79641edb306SCy Schubert nl->nl_pkts[0], nl->nl_pkts[1], 79741edb306SCy Schubert nl->nl_bytes[0], nl->nl_bytes[1]); 79841edb306SCy Schubert t += strlen(t); 79941edb306SCy Schubert } 80041edb306SCy Schubert 80141edb306SCy Schubert *t++ = '\n'; 80241edb306SCy Schubert *t++ = '\0'; 80341edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 80441edb306SCy Schubert syslog(LOG_INFO, "%s", line); 80541edb306SCy Schubert else if (conf->log != NULL) 80641edb306SCy Schubert (void) fprintf(conf->log, "%s", line); 80741edb306SCy Schubert } 80841edb306SCy Schubert 80941edb306SCy Schubert 810efeb8bffSCy Schubert static void 811efeb8bffSCy Schubert print_statelog(config_t *conf, char *buf, int blen) 81241edb306SCy Schubert { 81341edb306SCy Schubert static u_32_t seqnum = 0; 81441edb306SCy Schubert int res, i, len, family; 81541edb306SCy Schubert struct ipslog *sl; 81641edb306SCy Schubert char *t, *proto; 81741edb306SCy Schubert struct tm *tm; 81841edb306SCy Schubert iplog_t *ipl; 81941edb306SCy Schubert 82041edb306SCy Schubert t = line; 82141edb306SCy Schubert ipl = (iplog_t *)buf; 82241edb306SCy Schubert if (ipl->ipl_seqnum != seqnum) { 82341edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG) != 0) { 82441edb306SCy Schubert syslog(LOG_WARNING, 82541edb306SCy Schubert "missed %u state log entries: %u %u", 82641edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 82741edb306SCy Schubert ipl->ipl_seqnum); 82841edb306SCy Schubert } else { 82941edb306SCy Schubert (void) fprintf(conf->log, 83041edb306SCy Schubert "missed %u state log entries: %u %u\n", 83141edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 83241edb306SCy Schubert ipl->ipl_seqnum); 83341edb306SCy Schubert } 83441edb306SCy Schubert } 83541edb306SCy Schubert seqnum = ipl->ipl_seqnum + ipl->ipl_count; 83641edb306SCy Schubert 83741edb306SCy Schubert sl = (struct ipslog *)((char *)ipl + sizeof(*ipl)); 83841edb306SCy Schubert res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 83941edb306SCy Schubert tm = get_tm(ipl->ipl_sec); 84041edb306SCy Schubert len = sizeof(line); 84141edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 84241edb306SCy Schubert (void) strftime(t, len, "%d/%m/%Y ", tm); 84341edb306SCy Schubert i = strlen(t); 84441edb306SCy Schubert len -= i; 84541edb306SCy Schubert t += i; 84641edb306SCy Schubert } 84741edb306SCy Schubert (void) strftime(t, len, "%T", tm); 84841edb306SCy Schubert t += strlen(t); 849d740faa3SCy Schubert sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 85041edb306SCy Schubert t += strlen(t); 85141edb306SCy Schubert 85241edb306SCy Schubert family = vtof(sl->isl_v); 85341edb306SCy Schubert 85441edb306SCy Schubert switch (sl->isl_type) 85541edb306SCy Schubert { 85641edb306SCy Schubert case ISL_NEW : 85741edb306SCy Schubert strcpy(t, "STATE:NEW "); 85841edb306SCy Schubert break; 85941edb306SCy Schubert 86041edb306SCy Schubert case ISL_CLONE : 86141edb306SCy Schubert strcpy(t, "STATE:CLONED "); 86241edb306SCy Schubert break; 86341edb306SCy Schubert 86441edb306SCy Schubert case ISL_EXPIRE : 86541edb306SCy Schubert if ((sl->isl_p == IPPROTO_TCP) && 86641edb306SCy Schubert (sl->isl_state[0] > IPF_TCPS_ESTABLISHED || 86741edb306SCy Schubert sl->isl_state[1] > IPF_TCPS_ESTABLISHED)) 86841edb306SCy Schubert strcpy(t, "STATE:CLOSE "); 86941edb306SCy Schubert else 87041edb306SCy Schubert strcpy(t, "STATE:EXPIRE "); 87141edb306SCy Schubert break; 87241edb306SCy Schubert 87341edb306SCy Schubert case ISL_FLUSH : 87441edb306SCy Schubert strcpy(t, "STATE:FLUSH "); 87541edb306SCy Schubert break; 87641edb306SCy Schubert 87741edb306SCy Schubert case ISL_INTERMEDIATE : 87841edb306SCy Schubert strcpy(t, "STATE:INTERMEDIATE "); 87941edb306SCy Schubert break; 88041edb306SCy Schubert 88141edb306SCy Schubert case ISL_REMOVE : 88241edb306SCy Schubert strcpy(t, "STATE:REMOVE "); 88341edb306SCy Schubert break; 88441edb306SCy Schubert 88541edb306SCy Schubert case ISL_KILLED : 88641edb306SCy Schubert strcpy(t, "STATE:KILLED "); 88741edb306SCy Schubert break; 88841edb306SCy Schubert 88941edb306SCy Schubert case ISL_UNLOAD : 89041edb306SCy Schubert strcpy(t, "STATE:UNLOAD "); 89141edb306SCy Schubert break; 89241edb306SCy Schubert 89341edb306SCy Schubert default : 894d740faa3SCy Schubert sprintf(t, "Type: %d ", sl->isl_type); 89541edb306SCy Schubert break; 89641edb306SCy Schubert } 89741edb306SCy Schubert t += strlen(t); 89841edb306SCy Schubert 89941edb306SCy Schubert proto = getlocalproto(sl->isl_p); 90041edb306SCy Schubert 90141edb306SCy Schubert if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) { 902d740faa3SCy Schubert sprintf(t, "%s,%s -> ", 90341edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_src), 90441edb306SCy Schubert portlocalname(res, proto, (u_int)sl->isl_sport)); 90541edb306SCy Schubert t += strlen(t); 906d740faa3SCy Schubert sprintf(t, "%s,%s PR %s", 90741edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), 90841edb306SCy Schubert portlocalname(res, proto, (u_int)sl->isl_dport), proto); 90941edb306SCy Schubert } else if (sl->isl_p == IPPROTO_ICMP) { 910d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 91141edb306SCy Schubert t += strlen(t); 912d740faa3SCy Schubert sprintf(t, "%s PR icmp %d", 91341edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), 91441edb306SCy Schubert sl->isl_itype); 91541edb306SCy Schubert } else if (sl->isl_p == IPPROTO_ICMPV6) { 916d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 91741edb306SCy Schubert t += strlen(t); 918d740faa3SCy Schubert sprintf(t, "%s PR icmpv6 %d", 91941edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), 92041edb306SCy Schubert sl->isl_itype); 92141edb306SCy Schubert } else { 922d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src)); 92341edb306SCy Schubert t += strlen(t); 924d740faa3SCy Schubert sprintf(t, "%s PR %s", 92541edb306SCy Schubert hostname(family, (u_32_t *)&sl->isl_dst), proto); 92641edb306SCy Schubert } 92741edb306SCy Schubert t += strlen(t); 92841edb306SCy Schubert if (sl->isl_tag != FR_NOLOGTAG) { 929d740faa3SCy Schubert sprintf(t, " tag %u", sl->isl_tag); 93041edb306SCy Schubert t += strlen(t); 93141edb306SCy Schubert } 93241edb306SCy Schubert if (sl->isl_type != ISL_NEW) { 933d740faa3SCy Schubert sprintf(t, 93441edb306SCy Schubert #ifdef USE_QUAD_T 93541edb306SCy Schubert #ifdef PRId64 93641edb306SCy Schubert " Forward: Pkts in %" PRId64 " Bytes in %" PRId64 93741edb306SCy Schubert " Pkts out %" PRId64 " Bytes out %" PRId64 93841edb306SCy Schubert " Backward: Pkts in %" PRId64 " Bytes in %" PRId64 93941edb306SCy Schubert " Pkts out %" PRId64 " Bytes out %" PRId64, 94041edb306SCy Schubert #else 94141edb306SCy 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", 94241edb306SCy Schubert #endif /* PRId64 */ 94341edb306SCy Schubert #else 94441edb306SCy 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", 94541edb306SCy Schubert #endif 94641edb306SCy Schubert sl->isl_pkts[0], sl->isl_bytes[0], 94741edb306SCy Schubert sl->isl_pkts[1], sl->isl_bytes[1], 94841edb306SCy Schubert sl->isl_pkts[2], sl->isl_bytes[2], 94941edb306SCy Schubert sl->isl_pkts[3], sl->isl_bytes[3]); 95041edb306SCy Schubert 95141edb306SCy Schubert t += strlen(t); 95241edb306SCy Schubert } 95341edb306SCy Schubert 95441edb306SCy Schubert *t++ = '\n'; 95541edb306SCy Schubert *t++ = '\0'; 95641edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 95741edb306SCy Schubert syslog(LOG_INFO, "%s", line); 95841edb306SCy Schubert else if (conf->log != NULL) 95941edb306SCy Schubert (void) fprintf(conf->log, "%s", line); 96041edb306SCy Schubert } 96141edb306SCy Schubert 96241edb306SCy Schubert 963efeb8bffSCy Schubert static void 964efeb8bffSCy Schubert print_log(config_t *conf, logsource_t *log, char *buf, int blen) 96541edb306SCy Schubert { 96641edb306SCy Schubert char *bp, *bpo; 96741edb306SCy Schubert iplog_t *ipl; 96841edb306SCy Schubert int psize; 96941edb306SCy Schubert 97041edb306SCy Schubert bp = NULL; 97141edb306SCy Schubert bpo = NULL; 97241edb306SCy Schubert 97341edb306SCy Schubert while (blen > 0) { 97441edb306SCy Schubert ipl = (iplog_t *)buf; 97541edb306SCy Schubert if ((u_long)ipl & (sizeof(long)-1)) { 97641edb306SCy Schubert if (bp) 97741edb306SCy Schubert bpo = bp; 97841edb306SCy Schubert bp = (char *)malloc(blen); 97941edb306SCy Schubert bcopy((char *)ipl, bp, blen); 98041edb306SCy Schubert if (bpo) { 98141edb306SCy Schubert free(bpo); 98241edb306SCy Schubert bpo = NULL; 98341edb306SCy Schubert } 98441edb306SCy Schubert buf = bp; 98541edb306SCy Schubert continue; 98641edb306SCy Schubert } 98741edb306SCy Schubert 98841edb306SCy Schubert psize = ipl->ipl_dsize; 98941edb306SCy Schubert if (psize > blen) 99041edb306SCy Schubert break; 99141edb306SCy Schubert 99241edb306SCy Schubert if (conf->blog != NULL) { 99341edb306SCy Schubert fwrite(buf, psize, 1, conf->blog); 99441edb306SCy Schubert fflush(conf->blog); 99541edb306SCy Schubert } 99641edb306SCy Schubert 99741edb306SCy Schubert if (log->logtype == IPL_LOGIPF) { 99841edb306SCy Schubert if (ipl->ipl_magic == IPL_MAGIC) 99941edb306SCy Schubert print_ipflog(conf, buf, psize); 100041edb306SCy Schubert 100141edb306SCy Schubert } else if (log->logtype == IPL_LOGNAT) { 100241edb306SCy Schubert if (ipl->ipl_magic == IPL_MAGIC_NAT) 100341edb306SCy Schubert print_natlog(conf, buf, psize); 100441edb306SCy Schubert 100541edb306SCy Schubert } else if (log->logtype == IPL_LOGSTATE) { 100641edb306SCy Schubert if (ipl->ipl_magic == IPL_MAGIC_STATE) 100741edb306SCy Schubert print_statelog(conf, buf, psize); 100841edb306SCy Schubert } 100941edb306SCy Schubert 101041edb306SCy Schubert blen -= psize; 101141edb306SCy Schubert buf += psize; 101241edb306SCy Schubert } 101341edb306SCy Schubert if (bp) 101441edb306SCy Schubert free(bp); 101541edb306SCy Schubert return; 101641edb306SCy Schubert } 101741edb306SCy Schubert 101841edb306SCy Schubert 1019efeb8bffSCy Schubert static void 1020efeb8bffSCy Schubert print_ipflog(config_t *conf, char *buf, int blen) 102141edb306SCy Schubert { 102241edb306SCy Schubert static u_32_t seqnum = 0; 102341edb306SCy Schubert int i, f, lvl, res, len, off, plen, ipoff, defaction; 102441edb306SCy Schubert struct icmp *icmp; 102541edb306SCy Schubert struct icmp *ic; 102641edb306SCy Schubert char *t, *proto; 102741edb306SCy Schubert ip_t *ipc, *ip; 102841edb306SCy Schubert struct tm *tm; 102941edb306SCy Schubert u_32_t *s, *d; 103041edb306SCy Schubert u_short hl, p; 103141edb306SCy Schubert ipflog_t *ipf; 103241edb306SCy Schubert iplog_t *ipl; 103341edb306SCy Schubert tcphdr_t *tp; 103441edb306SCy Schubert #ifdef USE_INET6 103541edb306SCy Schubert struct ip6_ext *ehp; 103641edb306SCy Schubert u_short ehl; 103741edb306SCy Schubert ip6_t *ip6; 103841edb306SCy Schubert int go; 103941edb306SCy Schubert #endif 104041edb306SCy Schubert 104141edb306SCy Schubert ipl = (iplog_t *)buf; 104241edb306SCy Schubert if (ipl->ipl_seqnum != seqnum) { 104341edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG) != 0) { 104441edb306SCy Schubert syslog(LOG_WARNING, 104541edb306SCy Schubert "missed %u ipf log entries: %u %u", 104641edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 104741edb306SCy Schubert ipl->ipl_seqnum); 104841edb306SCy Schubert } else { 104941edb306SCy Schubert (void) fprintf(conf->log, 105041edb306SCy Schubert "missed %u ipf log entries: %u %u\n", 105141edb306SCy Schubert ipl->ipl_seqnum - seqnum, seqnum, 105241edb306SCy Schubert ipl->ipl_seqnum); 105341edb306SCy Schubert } 105441edb306SCy Schubert } 105541edb306SCy Schubert seqnum = ipl->ipl_seqnum + ipl->ipl_count; 105641edb306SCy Schubert 105741edb306SCy Schubert ipf = (ipflog_t *)((char *)buf + sizeof(*ipl)); 105841edb306SCy Schubert ip = (ip_t *)((char *)ipf + sizeof(*ipf)); 105941edb306SCy Schubert f = ipf->fl_family; 106041edb306SCy Schubert res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0; 106141edb306SCy Schubert t = line; 106241edb306SCy Schubert *t = '\0'; 106341edb306SCy Schubert tm = get_tm(ipl->ipl_sec); 106441edb306SCy Schubert 106541edb306SCy Schubert len = sizeof(line); 106641edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 106741edb306SCy Schubert (void) strftime(t, len, "%d/%m/%Y ", tm); 106841edb306SCy Schubert i = strlen(t); 106941edb306SCy Schubert len -= i; 107041edb306SCy Schubert t += i; 107141edb306SCy Schubert } 107241edb306SCy Schubert (void) strftime(t, len, "%T", tm); 107341edb306SCy Schubert t += strlen(t); 1074d740faa3SCy Schubert sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec); 107541edb306SCy Schubert t += strlen(t); 107641edb306SCy Schubert if (ipl->ipl_count > 1) { 1077d740faa3SCy Schubert sprintf(t, "%dx ", ipl->ipl_count); 107841edb306SCy Schubert t += strlen(t); 107941edb306SCy Schubert } 108041edb306SCy Schubert { 108141edb306SCy Schubert char ifname[sizeof(ipf->fl_ifname) + 1]; 108241edb306SCy Schubert 108341edb306SCy Schubert strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname)); 108441edb306SCy Schubert ifname[sizeof(ipf->fl_ifname)] = '\0'; 1085d740faa3SCy Schubert sprintf(t, "%s", ifname); 108641edb306SCy Schubert t += strlen(t); 108741edb306SCy Schubert # if SOLARIS 108841edb306SCy Schubert if (ISALPHA(*(t - 1))) { 1089d740faa3SCy Schubert sprintf(t, "%d", ipf->fl_unit); 109041edb306SCy Schubert t += strlen(t); 109141edb306SCy Schubert } 109241edb306SCy Schubert # endif 109341edb306SCy Schubert } 109441edb306SCy Schubert if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0')) 109541edb306SCy Schubert strcat(t, " @-1:"); 109641edb306SCy Schubert else if (ipf->fl_group[0] == '\0') 109741edb306SCy Schubert (void) strcpy(t, " @0:"); 109841edb306SCy Schubert else 1099d740faa3SCy Schubert sprintf(t, " @%s:", ipf->fl_group); 110041edb306SCy Schubert t += strlen(t); 110141edb306SCy Schubert if (ipf->fl_rule == 0xffffffff) 110241edb306SCy Schubert strcat(t, "-1 "); 110341edb306SCy Schubert else 1104d740faa3SCy Schubert sprintf(t, "%u ", ipf->fl_rule + 1); 110541edb306SCy Schubert t += strlen(t); 110641edb306SCy Schubert 110741edb306SCy Schubert lvl = LOG_NOTICE; 110841edb306SCy Schubert 110941edb306SCy Schubert if (ipf->fl_lflags & FI_SHORT) { 111041edb306SCy Schubert *t++ = 'S'; 111141edb306SCy Schubert lvl = LOG_ERR; 111241edb306SCy Schubert } 111341edb306SCy Schubert 111441edb306SCy Schubert if (FR_ISPASS(ipf->fl_flags)) { 111541edb306SCy Schubert if (ipf->fl_flags & FR_LOGP) 111641edb306SCy Schubert *t++ = 'p'; 111741edb306SCy Schubert else 111841edb306SCy Schubert *t++ = 'P'; 111941edb306SCy Schubert } else if (FR_ISBLOCK(ipf->fl_flags)) { 112041edb306SCy Schubert if (ipf->fl_flags & FR_LOGB) 112141edb306SCy Schubert *t++ = 'b'; 112241edb306SCy Schubert else 112341edb306SCy Schubert *t++ = 'B'; 112441edb306SCy Schubert lvl = LOG_WARNING; 112541edb306SCy Schubert } else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) { 112641edb306SCy Schubert *t++ = 'L'; 112741edb306SCy Schubert lvl = LOG_INFO; 112841edb306SCy Schubert } else if (ipf->fl_flags & FF_LOGNOMATCH) { 112941edb306SCy Schubert *t++ = 'n'; 113041edb306SCy Schubert } else { 113141edb306SCy Schubert *t++ = '?'; 113241edb306SCy Schubert lvl = LOG_EMERG; 113341edb306SCy Schubert } 113441edb306SCy Schubert if (ipf->fl_loglevel != 0xffff) 113541edb306SCy Schubert lvl = ipf->fl_loglevel; 113641edb306SCy Schubert *t++ = ' '; 113741edb306SCy Schubert *t = '\0'; 113841edb306SCy Schubert 113941edb306SCy Schubert if (f == AF_INET) { 114041edb306SCy Schubert hl = IP_HL(ip) << 2; 114141edb306SCy Schubert ipoff = ntohs(ip->ip_off); 114241edb306SCy Schubert off = ipoff & IP_OFFMASK; 114341edb306SCy Schubert p = (u_short)ip->ip_p; 114441edb306SCy Schubert s = (u_32_t *)&ip->ip_src; 114541edb306SCy Schubert d = (u_32_t *)&ip->ip_dst; 114641edb306SCy Schubert plen = ntohs(ip->ip_len); 114741edb306SCy Schubert } else 114841edb306SCy Schubert #ifdef USE_INET6 114941edb306SCy Schubert if (f == AF_INET6) { 115041edb306SCy Schubert off = 0; 115141edb306SCy Schubert ipoff = 0; 115241edb306SCy Schubert hl = sizeof(ip6_t); 115341edb306SCy Schubert ip6 = (ip6_t *)ip; 115441edb306SCy Schubert p = (u_short)ip6->ip6_nxt; 115541edb306SCy Schubert s = (u_32_t *)&ip6->ip6_src; 115641edb306SCy Schubert d = (u_32_t *)&ip6->ip6_dst; 115741edb306SCy Schubert plen = hl + ntohs(ip6->ip6_plen); 115841edb306SCy Schubert go = 1; 115941edb306SCy Schubert ehp = (struct ip6_ext *)((char *)ip6 + hl); 116041edb306SCy Schubert while (go == 1) { 116141edb306SCy Schubert switch (p) 116241edb306SCy Schubert { 116341edb306SCy Schubert case IPPROTO_HOPOPTS : 116441edb306SCy Schubert case IPPROTO_MOBILITY : 116541edb306SCy Schubert case IPPROTO_DSTOPTS : 116641edb306SCy Schubert case IPPROTO_ROUTING : 116741edb306SCy Schubert case IPPROTO_AH : 116841edb306SCy Schubert p = ehp->ip6e_nxt; 116941edb306SCy Schubert ehl = 8 + (ehp->ip6e_len << 3); 117041edb306SCy Schubert hl += ehl; 117141edb306SCy Schubert ehp = (struct ip6_ext *)((char *)ehp + ehl); 117241edb306SCy Schubert break; 117341edb306SCy Schubert case IPPROTO_FRAGMENT : 117441edb306SCy Schubert hl += sizeof(struct ip6_frag); 117541edb306SCy Schubert /* FALLTHROUGH */ 117641edb306SCy Schubert default : 117741edb306SCy Schubert go = 0; 117841edb306SCy Schubert break; 117941edb306SCy Schubert } 118041edb306SCy Schubert } 118141edb306SCy Schubert } else 118241edb306SCy Schubert #endif 118341edb306SCy Schubert { 118441edb306SCy Schubert goto printipflog; 118541edb306SCy Schubert } 118641edb306SCy Schubert proto = getlocalproto(p); 118741edb306SCy Schubert 118841edb306SCy Schubert if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) { 118941edb306SCy Schubert tp = (tcphdr_t *)((char *)ip + hl); 119041edb306SCy Schubert if (!(ipf->fl_lflags & FI_SHORT)) { 1191d740faa3SCy Schubert sprintf(t, "%s,%s -> ", hostname(f, s), 119241edb306SCy Schubert portlocalname(res, proto, (u_int)tp->th_sport)); 119341edb306SCy Schubert t += strlen(t); 1194d740faa3SCy Schubert sprintf(t, "%s,%s PR %s len %hu %hu", 119541edb306SCy Schubert hostname(f, d), 119641edb306SCy Schubert portlocalname(res, proto, (u_int)tp->th_dport), 119741edb306SCy Schubert proto, hl, plen); 119841edb306SCy Schubert t += strlen(t); 119941edb306SCy Schubert 120041edb306SCy Schubert if (p == IPPROTO_TCP) { 120141edb306SCy Schubert *t++ = ' '; 120241edb306SCy Schubert *t++ = '-'; 120341edb306SCy Schubert for (i = 0; tcpfl[i].value; i++) 120441edb306SCy Schubert if (tp->th_flags & tcpfl[i].value) 120541edb306SCy Schubert *t++ = tcpfl[i].flag; 120641edb306SCy Schubert if (ipmonopts & IPMON_VERBOSE) { 1207d740faa3SCy Schubert sprintf(t, " %lu %lu %hu", 120841edb306SCy Schubert (u_long)(ntohl(tp->th_seq)), 120941edb306SCy Schubert (u_long)(ntohl(tp->th_ack)), 121041edb306SCy Schubert ntohs(tp->th_win)); 121141edb306SCy Schubert t += strlen(t); 121241edb306SCy Schubert } 121341edb306SCy Schubert } 121441edb306SCy Schubert *t = '\0'; 121541edb306SCy Schubert } else { 1216d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 121741edb306SCy Schubert t += strlen(t); 121841edb306SCy Schubert sprintf(t, "%s PR %s len %hu %hu", 121941edb306SCy Schubert hostname(f, d), proto, hl, plen); 122041edb306SCy Schubert } 122141edb306SCy Schubert #if defined(AF_INET6) && defined(IPPROTO_ICMPV6) 122241edb306SCy Schubert } else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) { 122341edb306SCy Schubert ic = (struct icmp *)((char *)ip + hl); 1224d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 122541edb306SCy Schubert t += strlen(t); 1226d740faa3SCy Schubert sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s", 122741edb306SCy Schubert hostname(f, d), hl, plen, 122841edb306SCy Schubert icmpname6(ic->icmp_type, ic->icmp_code)); 122941edb306SCy Schubert #endif 123041edb306SCy Schubert } else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) { 123141edb306SCy Schubert ic = (struct icmp *)((char *)ip + hl); 1232d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 123341edb306SCy Schubert t += strlen(t); 1234d740faa3SCy Schubert sprintf(t, "%s PR icmp len %hu %hu icmp %s", 123541edb306SCy Schubert hostname(f, d), hl, plen, 123641edb306SCy Schubert icmpname(ic->icmp_type, ic->icmp_code)); 123741edb306SCy Schubert if (ic->icmp_type == ICMP_UNREACH || 123841edb306SCy Schubert ic->icmp_type == ICMP_SOURCEQUENCH || 123941edb306SCy Schubert ic->icmp_type == ICMP_PARAMPROB || 124041edb306SCy Schubert ic->icmp_type == ICMP_REDIRECT || 124141edb306SCy Schubert ic->icmp_type == ICMP_TIMXCEED) { 124241edb306SCy Schubert ipc = &ic->icmp_ip; 124341edb306SCy Schubert i = ntohs(ipc->ip_len); 124441edb306SCy Schubert /* 124541edb306SCy Schubert * XXX - try to guess endian of ip_len in ICMP 124641edb306SCy Schubert * returned data. 124741edb306SCy Schubert */ 124841edb306SCy Schubert if (i > 1500) 124941edb306SCy Schubert i = ipc->ip_len; 125041edb306SCy Schubert ipoff = ntohs(ipc->ip_off); 125141edb306SCy Schubert proto = getlocalproto(ipc->ip_p); 125241edb306SCy Schubert 125341edb306SCy Schubert if (!(ipoff & IP_OFFMASK) && 125441edb306SCy Schubert ((ipc->ip_p == IPPROTO_TCP) || 125541edb306SCy Schubert (ipc->ip_p == IPPROTO_UDP))) { 125641edb306SCy Schubert tp = (tcphdr_t *)((char *)ipc + hl); 125741edb306SCy Schubert t += strlen(t); 1258d740faa3SCy Schubert sprintf(t, " for %s,%s -", 125941edb306SCy Schubert HOSTNAMEV4(ipc->ip_src), 126041edb306SCy Schubert portlocalname(res, proto, 126141edb306SCy Schubert (u_int)tp->th_sport)); 126241edb306SCy Schubert t += strlen(t); 1263d740faa3SCy Schubert sprintf(t, " %s,%s PR %s len %hu %hu", 126441edb306SCy Schubert HOSTNAMEV4(ipc->ip_dst), 126541edb306SCy Schubert portlocalname(res, proto, 126641edb306SCy Schubert (u_int)tp->th_dport), 126741edb306SCy Schubert proto, IP_HL(ipc) << 2, i); 126841edb306SCy Schubert } else if (!(ipoff & IP_OFFMASK) && 126941edb306SCy Schubert (ipc->ip_p == IPPROTO_ICMP)) { 127041edb306SCy Schubert icmp = (icmphdr_t *)((char *)ipc + hl); 127141edb306SCy Schubert 127241edb306SCy Schubert t += strlen(t); 1273d740faa3SCy Schubert sprintf(t, " for %s -", 127441edb306SCy Schubert HOSTNAMEV4(ipc->ip_src)); 127541edb306SCy Schubert t += strlen(t); 1276d740faa3SCy Schubert sprintf(t, 127741edb306SCy Schubert " %s PR icmp len %hu %hu icmp %d/%d", 127841edb306SCy Schubert HOSTNAMEV4(ipc->ip_dst), 127941edb306SCy Schubert IP_HL(ipc) << 2, i, 128041edb306SCy Schubert icmp->icmp_type, icmp->icmp_code); 128141edb306SCy Schubert } else { 128241edb306SCy Schubert t += strlen(t); 1283d740faa3SCy Schubert sprintf(t, " for %s -", 128441edb306SCy Schubert HOSTNAMEV4(ipc->ip_src)); 128541edb306SCy Schubert t += strlen(t); 1286d740faa3SCy Schubert sprintf(t, " %s PR %s len %hu (%hu)", 128741edb306SCy Schubert HOSTNAMEV4(ipc->ip_dst), proto, 128841edb306SCy Schubert IP_HL(ipc) << 2, i); 128941edb306SCy Schubert t += strlen(t); 129041edb306SCy Schubert if (ipoff & IP_OFFMASK) { 1291d740faa3SCy Schubert sprintf(t, "(frag %d:%hu@%hu%s%s)", 129241edb306SCy Schubert ntohs(ipc->ip_id), 129341edb306SCy Schubert i - (IP_HL(ipc) << 2), 129441edb306SCy Schubert (ipoff & IP_OFFMASK) << 3, 129541edb306SCy Schubert ipoff & IP_MF ? "+" : "", 129641edb306SCy Schubert ipoff & IP_DF ? "-" : ""); 129741edb306SCy Schubert } 129841edb306SCy Schubert } 129941edb306SCy Schubert 130041edb306SCy Schubert } 130141edb306SCy Schubert } else { 1302d740faa3SCy Schubert sprintf(t, "%s -> ", hostname(f, s)); 130341edb306SCy Schubert t += strlen(t); 1304d740faa3SCy Schubert sprintf(t, "%s PR %s len %hu (%hu)", 130541edb306SCy Schubert hostname(f, d), proto, hl, plen); 130641edb306SCy Schubert t += strlen(t); 130741edb306SCy Schubert if (off & IP_OFFMASK) 1308d740faa3SCy Schubert sprintf(t, " (frag %d:%hu@%hu%s%s)", 130941edb306SCy Schubert ntohs(ip->ip_id), 131041edb306SCy Schubert plen - hl, (off & IP_OFFMASK) << 3, 131141edb306SCy Schubert ipoff & IP_MF ? "+" : "", 131241edb306SCy Schubert ipoff & IP_DF ? "-" : ""); 131341edb306SCy Schubert } 131441edb306SCy Schubert t += strlen(t); 131541edb306SCy Schubert 131641edb306SCy Schubert printipflog: 131741edb306SCy Schubert if (ipf->fl_flags & FR_KEEPSTATE) { 131841edb306SCy Schubert (void) strcpy(t, " K-S"); 131941edb306SCy Schubert t += strlen(t); 132041edb306SCy Schubert } 132141edb306SCy Schubert 132241edb306SCy Schubert if (ipf->fl_flags & FR_KEEPFRAG) { 132341edb306SCy Schubert (void) strcpy(t, " K-F"); 132441edb306SCy Schubert t += strlen(t); 132541edb306SCy Schubert } 132641edb306SCy Schubert 132741edb306SCy Schubert if (ipf->fl_dir == 0) 132841edb306SCy Schubert strcpy(t, " IN"); 132941edb306SCy Schubert else if (ipf->fl_dir == 1) 133041edb306SCy Schubert strcpy(t, " OUT"); 133141edb306SCy Schubert t += strlen(t); 133241edb306SCy Schubert if (ipf->fl_logtag != 0) { 1333d740faa3SCy Schubert sprintf(t, " log-tag %d", ipf->fl_logtag); 133441edb306SCy Schubert t += strlen(t); 133541edb306SCy Schubert } 133641edb306SCy Schubert if (ipf->fl_nattag.ipt_num[0] != 0) { 133741edb306SCy Schubert strcpy(t, " nat-tag "); 133841edb306SCy Schubert t += strlen(t); 133941edb306SCy Schubert strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag)); 134041edb306SCy Schubert t += strlen(t); 134141edb306SCy Schubert } 134241edb306SCy Schubert if ((ipf->fl_lflags & FI_LOWTTL) != 0) { 134341edb306SCy Schubert strcpy(t, " low-ttl"); 134441edb306SCy Schubert t += 8; 134541edb306SCy Schubert } 134641edb306SCy Schubert if ((ipf->fl_lflags & FI_OOW) != 0) { 134741edb306SCy Schubert strcpy(t, " OOW"); 134841edb306SCy Schubert t += 4; 134941edb306SCy Schubert } 135041edb306SCy Schubert if ((ipf->fl_lflags & FI_BAD) != 0) { 135141edb306SCy Schubert strcpy(t, " bad"); 135241edb306SCy Schubert t += 4; 135341edb306SCy Schubert } 135441edb306SCy Schubert if ((ipf->fl_lflags & FI_NATED) != 0) { 135541edb306SCy Schubert strcpy(t, " NAT"); 135641edb306SCy Schubert t += 4; 135741edb306SCy Schubert } 135841edb306SCy Schubert if ((ipf->fl_lflags & FI_BADNAT) != 0) { 135941edb306SCy Schubert strcpy(t, " bad-NAT"); 136041edb306SCy Schubert t += 8; 136141edb306SCy Schubert } 136241edb306SCy Schubert if ((ipf->fl_lflags & FI_BADSRC) != 0) { 136341edb306SCy Schubert strcpy(t, " bad-src"); 136441edb306SCy Schubert t += 8; 136541edb306SCy Schubert } 136641edb306SCy Schubert if ((ipf->fl_lflags & FI_MULTICAST) != 0) { 136741edb306SCy Schubert strcpy(t, " multicast"); 136841edb306SCy Schubert t += 10; 136941edb306SCy Schubert } 137041edb306SCy Schubert if ((ipf->fl_lflags & FI_BROADCAST) != 0) { 137141edb306SCy Schubert strcpy(t, " broadcast"); 137241edb306SCy Schubert t += 10; 137341edb306SCy Schubert } 137441edb306SCy Schubert if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) == 137541edb306SCy Schubert FI_MBCAST) { 137641edb306SCy Schubert strcpy(t, " mbcast"); 137741edb306SCy Schubert t += 7; 137841edb306SCy Schubert } 137941edb306SCy Schubert if (ipf->fl_breason != 0) { 138041edb306SCy Schubert strcpy(t, " reason:"); 138141edb306SCy Schubert t += 8; 138241edb306SCy Schubert strcpy(t, reasons[ipf->fl_breason]); 138341edb306SCy Schubert t += strlen(reasons[ipf->fl_breason]); 138441edb306SCy Schubert } 138541edb306SCy Schubert *t++ = '\n'; 138641edb306SCy Schubert *t++ = '\0'; 138741edb306SCy Schubert defaction = 0; 138841edb306SCy Schubert if (conf->cfile != NULL) 138941edb306SCy Schubert defaction = check_action(buf, line, ipmonopts, lvl); 139041edb306SCy Schubert 139141edb306SCy Schubert if (defaction == 0) { 139241edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) { 139341edb306SCy Schubert syslog(lvl, "%s", line); 139441edb306SCy Schubert } else if (conf->log != NULL) { 139541edb306SCy Schubert (void) fprintf(conf->log, "%s", line); 139641edb306SCy Schubert } 139741edb306SCy Schubert 139841edb306SCy Schubert if (ipmonopts & IPMON_HEXHDR) { 139941edb306SCy Schubert dumphex(conf->log, ipmonopts, buf, 140041edb306SCy Schubert sizeof(iplog_t) + sizeof(*ipf)); 140141edb306SCy Schubert } 140241edb306SCy Schubert if (ipmonopts & IPMON_HEXBODY) { 140341edb306SCy Schubert dumphex(conf->log, ipmonopts, (char *)ip, 140441edb306SCy Schubert ipf->fl_plen + ipf->fl_hlen); 140541edb306SCy Schubert } else if ((ipmonopts & IPMON_LOGBODY) && 140641edb306SCy Schubert (ipf->fl_flags & FR_LOGBODY)) { 140741edb306SCy Schubert dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen, 140841edb306SCy Schubert ipf->fl_plen); 140941edb306SCy Schubert } 141041edb306SCy Schubert } 141141edb306SCy Schubert } 141241edb306SCy Schubert 141341edb306SCy Schubert 1414efeb8bffSCy Schubert static void 1415efeb8bffSCy Schubert usage(char *prog) 141641edb306SCy Schubert { 141741edb306SCy Schubert fprintf(stderr, "Usage: %s [ -abDFhnpstvxX ] [ -B <binary-logfile> ] [ -C <config-file> ]\n" 141841edb306SCy Schubert "\t[ -f <device> ] [ -L <facility> ] [ -N <device> ]\n" 141941edb306SCy Schubert "\t[ -o [NSI] ] [ -O [NSI] ] [ -P <pidfile> ] [ -S <device> ]\n" 142041edb306SCy Schubert "\t[ <filename> ]\n", prog); 142141edb306SCy Schubert exit(1); 142241edb306SCy Schubert } 142341edb306SCy Schubert 142441edb306SCy Schubert 1425efeb8bffSCy Schubert static void 1426efeb8bffSCy Schubert write_pid(char *file) 142741edb306SCy Schubert { 142841edb306SCy Schubert FILE *fp = NULL; 142941edb306SCy Schubert int fd; 143041edb306SCy Schubert 143141edb306SCy Schubert if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) { 143241edb306SCy Schubert fp = fdopen(fd, "w"); 143341edb306SCy Schubert if (fp == NULL) { 143441edb306SCy Schubert close(fd); 143541edb306SCy Schubert fprintf(stderr, 143641edb306SCy Schubert "unable to open/create pid file: %s\n", file); 143741edb306SCy Schubert return; 143841edb306SCy Schubert } 143941edb306SCy Schubert fprintf(fp, "%d", getpid()); 144041edb306SCy Schubert fclose(fp); 144141edb306SCy Schubert } 144241edb306SCy Schubert } 144341edb306SCy Schubert 144441edb306SCy Schubert 1445efeb8bffSCy Schubert static void 1446efeb8bffSCy Schubert flushlogs(char *file, FILE *log) 144741edb306SCy Schubert { 144841edb306SCy Schubert int fd, flushed = 0; 144941edb306SCy Schubert 145041edb306SCy Schubert if ((fd = open(file, O_RDWR)) == -1) { 145141edb306SCy Schubert (void) fprintf(stderr, "%s: open: %s\n", 145241edb306SCy Schubert file, STRERROR(errno)); 145341edb306SCy Schubert exit(1); 145441edb306SCy Schubert } 145541edb306SCy Schubert 145641edb306SCy Schubert if (ioctl(fd, SIOCIPFFB, &flushed) == 0) { 145741edb306SCy Schubert printf("%d bytes flushed from log buffer\n", 145841edb306SCy Schubert flushed); 145941edb306SCy Schubert fflush(stdout); 146041edb306SCy Schubert } else 146141edb306SCy Schubert ipferror(fd, "SIOCIPFFB"); 146241edb306SCy Schubert (void) close(fd); 146341edb306SCy Schubert 146441edb306SCy Schubert if (flushed) { 146541edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) { 146641edb306SCy Schubert syslog(LOG_INFO, "%d bytes flushed from log\n", 146741edb306SCy Schubert flushed); 146841edb306SCy Schubert } else if ((log != stdout) && (log != NULL)) { 146941edb306SCy Schubert fprintf(log, "%d bytes flushed from log\n", flushed); 147041edb306SCy Schubert } 147141edb306SCy Schubert } 147241edb306SCy Schubert } 147341edb306SCy Schubert 147441edb306SCy Schubert 1475efeb8bffSCy Schubert static void 1476efeb8bffSCy Schubert logopts(int turnon, char *options) 147741edb306SCy Schubert { 147841edb306SCy Schubert int flags = 0; 147941edb306SCy Schubert char *s; 148041edb306SCy Schubert 148141edb306SCy Schubert for (s = options; *s; s++) 148241edb306SCy Schubert { 148341edb306SCy Schubert switch (*s) 148441edb306SCy Schubert { 148541edb306SCy Schubert case 'N' : 148641edb306SCy Schubert flags |= IPMON_NAT; 148741edb306SCy Schubert break; 148841edb306SCy Schubert case 'S' : 148941edb306SCy Schubert flags |= IPMON_STATE; 149041edb306SCy Schubert break; 149141edb306SCy Schubert case 'I' : 149241edb306SCy Schubert flags |= IPMON_FILTER; 149341edb306SCy Schubert break; 149441edb306SCy Schubert default : 149541edb306SCy Schubert fprintf(stderr, "Unknown log option %c\n", *s); 149641edb306SCy Schubert exit(1); 149741edb306SCy Schubert } 149841edb306SCy Schubert } 149941edb306SCy Schubert 150041edb306SCy Schubert if (turnon) 150141edb306SCy Schubert ipmonopts |= flags; 150241edb306SCy Schubert else 150341edb306SCy Schubert ipmonopts &= ~(flags); 150441edb306SCy Schubert } 150541edb306SCy Schubert 1506efeb8bffSCy Schubert static void 1507efeb8bffSCy Schubert initconfig(config_t *conf) 150841edb306SCy Schubert { 150941edb306SCy Schubert int i; 151041edb306SCy Schubert 151141edb306SCy Schubert memset(conf, 0, sizeof(*conf)); 151241edb306SCy Schubert 151341edb306SCy Schubert conf->log = stdout; 151441edb306SCy Schubert conf->maxfd = -1; 151541edb306SCy Schubert 151641edb306SCy Schubert for (i = 0; i < 3; i++) { 151741edb306SCy Schubert conf->logsrc[i].fd = -1; 151841edb306SCy Schubert conf->logsrc[i].logtype = -1; 151941edb306SCy Schubert conf->logsrc[i].regular = -1; 152041edb306SCy Schubert } 152141edb306SCy Schubert 152241edb306SCy Schubert conf->logsrc[0].file = IPL_NAME; 152341edb306SCy Schubert conf->logsrc[1].file = IPNAT_NAME; 152441edb306SCy Schubert conf->logsrc[2].file = IPSTATE_NAME; 152541edb306SCy Schubert 152641edb306SCy Schubert add_doing(&executesaver); 152741edb306SCy Schubert add_doing(&snmpv1saver); 152841edb306SCy Schubert add_doing(&snmpv2saver); 152941edb306SCy Schubert add_doing(&syslogsaver); 153041edb306SCy Schubert add_doing(&filesaver); 153141edb306SCy Schubert add_doing(¬hingsaver); 153241edb306SCy Schubert } 153341edb306SCy Schubert 153441edb306SCy Schubert 1535efeb8bffSCy Schubert int 1536efeb8bffSCy Schubert main(int argc, char *argv[]) 153741edb306SCy Schubert { 153841edb306SCy Schubert int doread, c, make_daemon = 0; 153941edb306SCy Schubert char *prog; 154041edb306SCy Schubert config_t config; 154141edb306SCy Schubert 154241edb306SCy Schubert prog = strrchr(argv[0], '/'); 154341edb306SCy Schubert if (prog == NULL) 154441edb306SCy Schubert prog = argv[0]; 154541edb306SCy Schubert else 154641edb306SCy Schubert prog++; 154741edb306SCy Schubert 154841edb306SCy Schubert initconfig(&config); 154941edb306SCy Schubert 155041edb306SCy Schubert while ((c = getopt(argc, argv, 155141edb306SCy Schubert "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1) 155241edb306SCy Schubert switch (c) 155341edb306SCy Schubert { 155441edb306SCy Schubert case 'a' : 155541edb306SCy Schubert ipmonopts |= IPMON_LOGALL; 155641edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 155741edb306SCy Schubert config.logsrc[1].logtype = IPL_LOGNAT; 155841edb306SCy Schubert config.logsrc[2].logtype = IPL_LOGSTATE; 155941edb306SCy Schubert break; 156041edb306SCy Schubert case 'b' : 156141edb306SCy Schubert ipmonopts |= IPMON_LOGBODY; 156241edb306SCy Schubert break; 156341edb306SCy Schubert case 'B' : 156441edb306SCy Schubert config.bfile = optarg; 156541edb306SCy Schubert config.blog = fopen(optarg, "a"); 156641edb306SCy Schubert break; 156741edb306SCy Schubert case 'C' : 156841edb306SCy Schubert config.cfile = optarg; 156941edb306SCy Schubert break; 157041edb306SCy Schubert case 'D' : 157141edb306SCy Schubert make_daemon = 1; 157241edb306SCy Schubert break; 157341edb306SCy Schubert case 'f' : case 'I' : 157441edb306SCy Schubert ipmonopts |= IPMON_FILTER; 157541edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 157641edb306SCy Schubert config.logsrc[0].file = optarg; 157741edb306SCy Schubert break; 157841edb306SCy Schubert case 'F' : 157941edb306SCy Schubert flushlogs(config.logsrc[0].file, config.log); 158041edb306SCy Schubert flushlogs(config.logsrc[1].file, config.log); 158141edb306SCy Schubert flushlogs(config.logsrc[2].file, config.log); 158241edb306SCy Schubert break; 158341edb306SCy Schubert case 'L' : 158441edb306SCy Schubert logfac = fac_findname(optarg); 158541edb306SCy Schubert if (logfac == -1) { 158641edb306SCy Schubert fprintf(stderr, 158741edb306SCy Schubert "Unknown syslog facility '%s'\n", 158841edb306SCy Schubert optarg); 158941edb306SCy Schubert exit(1); 159041edb306SCy Schubert } 159141edb306SCy Schubert break; 159241edb306SCy Schubert case 'n' : 159341edb306SCy Schubert ipmonopts |= IPMON_RESOLVE; 159441edb306SCy Schubert opts &= ~OPT_NORESOLVE; 159541edb306SCy Schubert break; 159641edb306SCy Schubert case 'N' : 159741edb306SCy Schubert ipmonopts |= IPMON_NAT; 159841edb306SCy Schubert config.logsrc[1].logtype = IPL_LOGNAT; 159941edb306SCy Schubert config.logsrc[1].file = optarg; 160041edb306SCy Schubert break; 160141edb306SCy Schubert case 'o' : case 'O' : 160241edb306SCy Schubert logopts(c == 'o', optarg); 160341edb306SCy Schubert if (ipmonopts & IPMON_FILTER) 160441edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 160541edb306SCy Schubert if (ipmonopts & IPMON_NAT) 160641edb306SCy Schubert config.logsrc[1].logtype = IPL_LOGNAT; 160741edb306SCy Schubert if (ipmonopts & IPMON_STATE) 160841edb306SCy Schubert config.logsrc[2].logtype = IPL_LOGSTATE; 160941edb306SCy Schubert break; 161041edb306SCy Schubert case 'p' : 161141edb306SCy Schubert ipmonopts |= IPMON_PORTNUM; 161241edb306SCy Schubert break; 161341edb306SCy Schubert case 'P' : 161441edb306SCy Schubert pidfile = optarg; 161541edb306SCy Schubert break; 161641edb306SCy Schubert case 's' : 161741edb306SCy Schubert ipmonopts |= IPMON_SYSLOG; 161841edb306SCy Schubert config.log = NULL; 161941edb306SCy Schubert break; 162041edb306SCy Schubert case 'S' : 162141edb306SCy Schubert ipmonopts |= IPMON_STATE; 162241edb306SCy Schubert config.logsrc[2].logtype = IPL_LOGSTATE; 162341edb306SCy Schubert config.logsrc[2].file = optarg; 162441edb306SCy Schubert break; 162541edb306SCy Schubert case 't' : 162641edb306SCy Schubert ipmonopts |= IPMON_TAIL; 162741edb306SCy Schubert break; 162841edb306SCy Schubert case 'v' : 162941edb306SCy Schubert ipmonopts |= IPMON_VERBOSE; 163041edb306SCy Schubert break; 163141edb306SCy Schubert case 'x' : 163241edb306SCy Schubert ipmonopts |= IPMON_HEXBODY; 163341edb306SCy Schubert break; 163441edb306SCy Schubert case 'X' : 163541edb306SCy Schubert ipmonopts |= IPMON_HEXHDR; 163641edb306SCy Schubert break; 163741edb306SCy Schubert default : 163841edb306SCy Schubert case 'h' : 163941edb306SCy Schubert case '?' : 164041edb306SCy Schubert usage(argv[0]); 164141edb306SCy Schubert } 164241edb306SCy Schubert 164341edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 164441edb306SCy Schubert openlog(prog, LOG_NDELAY|LOG_PID, logfac); 164541edb306SCy Schubert 164641edb306SCy Schubert init_tabs(); 164741edb306SCy Schubert if (config.cfile) 164841edb306SCy Schubert if (load_config(config.cfile) == -1) { 164941edb306SCy Schubert unload_config(); 165041edb306SCy Schubert exit(1); 165141edb306SCy Schubert } 165241edb306SCy Schubert 165341edb306SCy Schubert /* 165441edb306SCy Schubert * Default action is to only open the filter log file. 165541edb306SCy Schubert */ 165641edb306SCy Schubert if ((config.logsrc[0].logtype == -1) && 165741edb306SCy Schubert (config.logsrc[0].logtype == -1) && 165841edb306SCy Schubert (config.logsrc[0].logtype == -1)) 165941edb306SCy Schubert config.logsrc[0].logtype = IPL_LOGIPF; 166041edb306SCy Schubert 166141edb306SCy Schubert openlogs(&config); 166241edb306SCy Schubert 166341edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) { 166441edb306SCy Schubert config.file = argv[optind]; 166541edb306SCy Schubert config.log = config.file ? fopen(config.file, "a") : stdout; 166641edb306SCy Schubert if (config.log == NULL) { 166741edb306SCy Schubert (void) fprintf(stderr, "%s: fopen: %s\n", 166841edb306SCy Schubert argv[optind], STRERROR(errno)); 166941edb306SCy Schubert exit(1); 167041edb306SCy Schubert /* NOTREACHED */ 167141edb306SCy Schubert } 167241edb306SCy Schubert setvbuf(config.log, NULL, _IONBF, 0); 167341edb306SCy Schubert } else { 167441edb306SCy Schubert config.log = NULL; 167541edb306SCy Schubert } 167641edb306SCy Schubert 167741edb306SCy Schubert if (make_daemon && 167841edb306SCy Schubert ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) { 167941edb306SCy Schubert #ifdef BSD 168041edb306SCy Schubert daemon(0, !(ipmonopts & IPMON_SYSLOG)); 168141edb306SCy Schubert #else 168241edb306SCy Schubert int pid; 168341edb306SCy Schubert 168441edb306SCy Schubert switch (fork()) 168541edb306SCy Schubert { 168641edb306SCy Schubert case -1 : 168741edb306SCy Schubert (void) fprintf(stderr, "%s: fork() failed: %s\n", 168841edb306SCy Schubert argv[0], STRERROR(errno)); 168941edb306SCy Schubert exit(1); 169041edb306SCy Schubert /* NOTREACHED */ 169141edb306SCy Schubert case 0 : 169241edb306SCy Schubert break; 169341edb306SCy Schubert default : 169441edb306SCy Schubert exit(0); 169541edb306SCy Schubert } 169641edb306SCy Schubert 169741edb306SCy Schubert setsid(); 169841edb306SCy Schubert if ((ipmonopts & IPMON_SYSLOG)) 169941edb306SCy Schubert close(2); 170041edb306SCy Schubert #endif /* !BSD */ 170141edb306SCy Schubert close(0); 170241edb306SCy Schubert close(1); 170341edb306SCy Schubert write_pid(pidfile); 170441edb306SCy Schubert } 170541edb306SCy Schubert 170641edb306SCy Schubert signal(SIGHUP, handlehup); 170741edb306SCy Schubert 170841edb306SCy Schubert for (doread = 1; doread; ) 170941edb306SCy Schubert doread = read_loginfo(&config); 171041edb306SCy Schubert 171141edb306SCy Schubert unload_config(); 171241edb306SCy Schubert 171341edb306SCy Schubert return (0); 171441edb306SCy Schubert /* NOTREACHED */ 171541edb306SCy Schubert } 171641edb306SCy Schubert 171741edb306SCy Schubert 1718efeb8bffSCy Schubert static void 1719efeb8bffSCy Schubert openlogs(config_t *conf) 172041edb306SCy Schubert { 172141edb306SCy Schubert logsource_t *l; 172241edb306SCy Schubert struct stat sb; 172341edb306SCy Schubert int i; 172441edb306SCy Schubert 172541edb306SCy Schubert for (i = 0; i < 3; i++) { 172641edb306SCy Schubert l = &conf->logsrc[i]; 172741edb306SCy Schubert if (l->logtype == -1) 172841edb306SCy Schubert continue; 172941edb306SCy Schubert if (!strcmp(l->file, "-")) 173041edb306SCy Schubert l->fd = 0; 173141edb306SCy Schubert else { 173241edb306SCy Schubert if ((l->fd= open(l->file, O_RDONLY)) == -1) { 173341edb306SCy Schubert (void) fprintf(stderr, 173441edb306SCy Schubert "%s: open: %s\n", l->file, 173541edb306SCy Schubert STRERROR(errno)); 173641edb306SCy Schubert exit(1); 173741edb306SCy Schubert /* NOTREACHED */ 173841edb306SCy Schubert } 173941edb306SCy Schubert 174041edb306SCy Schubert if (fstat(l->fd, &sb) == -1) { 174141edb306SCy Schubert (void) fprintf(stderr, "%d: fstat: %s\n", 174241edb306SCy Schubert l->fd, STRERROR(errno)); 174341edb306SCy Schubert exit(1); 174441edb306SCy Schubert /* NOTREACHED */ 174541edb306SCy Schubert } 174641edb306SCy Schubert 174741edb306SCy Schubert l->regular = !S_ISCHR(sb.st_mode); 174841edb306SCy Schubert if (l->regular) 174941edb306SCy Schubert l->size = sb.st_size; 175041edb306SCy Schubert 175141edb306SCy Schubert FD_SET(l->fd, &conf->fdmr); 175241edb306SCy Schubert if (l->fd > conf->maxfd) 175341edb306SCy Schubert conf->maxfd = l->fd; 175441edb306SCy Schubert } 175541edb306SCy Schubert } 175641edb306SCy Schubert } 175741edb306SCy Schubert 175841edb306SCy Schubert 1759efeb8bffSCy Schubert static int 1760efeb8bffSCy Schubert read_loginfo(config_t *conf) 176141edb306SCy Schubert { 176241edb306SCy Schubert iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1]; 176341edb306SCy Schubert int n, tr, nr, i; 176441edb306SCy Schubert logsource_t *l; 176541edb306SCy Schubert fd_set fdr; 176641edb306SCy Schubert 176741edb306SCy Schubert fdr = conf->fdmr; 176841edb306SCy Schubert 176941edb306SCy Schubert n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL); 177041edb306SCy Schubert if (n == 0) 17712582ae57SCy Schubert return (1); 177241edb306SCy Schubert if (n == -1) { 177341edb306SCy Schubert if (errno == EINTR) 17742582ae57SCy Schubert return (1); 17752582ae57SCy Schubert return (-1); 177641edb306SCy Schubert } 177741edb306SCy Schubert 177841edb306SCy Schubert for (i = 0, nr = 0; i < 3; i++) { 177941edb306SCy Schubert l = &conf->logsrc[i]; 178041edb306SCy Schubert 178141edb306SCy Schubert if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr)) 178241edb306SCy Schubert continue; 178341edb306SCy Schubert 178441edb306SCy Schubert tr = 0; 178541edb306SCy Schubert if (l->regular) { 178641edb306SCy Schubert tr = (lseek(l->fd, 0, SEEK_CUR) < l->size); 178741edb306SCy Schubert if (!tr && !(ipmonopts & IPMON_TAIL)) 17882582ae57SCy Schubert return (0); 178941edb306SCy Schubert } 179041edb306SCy Schubert 179141edb306SCy Schubert n = 0; 179241edb306SCy Schubert tr = read_log(l->fd, &n, (char *)buf, sizeof(buf)); 179341edb306SCy Schubert if (donehup) { 179441edb306SCy Schubert if (conf->file != NULL) { 179541edb306SCy Schubert if (conf->log != NULL) { 179641edb306SCy Schubert fclose(conf->log); 179741edb306SCy Schubert conf->log = NULL; 179841edb306SCy Schubert } 179941edb306SCy Schubert conf->log = fopen(conf->file, "a"); 180041edb306SCy Schubert } 180141edb306SCy Schubert 180241edb306SCy Schubert if (conf->bfile != NULL) { 180341edb306SCy Schubert if (conf->blog != NULL) { 180441edb306SCy Schubert fclose(conf->blog); 180541edb306SCy Schubert conf->blog = NULL; 180641edb306SCy Schubert } 180741edb306SCy Schubert conf->blog = fopen(conf->bfile, "a"); 180841edb306SCy Schubert } 180941edb306SCy Schubert 181041edb306SCy Schubert init_tabs(); 181141edb306SCy Schubert if (conf->cfile != NULL) 181241edb306SCy Schubert load_config(conf->cfile); 181341edb306SCy Schubert donehup = 0; 181441edb306SCy Schubert } 181541edb306SCy Schubert 181641edb306SCy Schubert switch (tr) 181741edb306SCy Schubert { 181841edb306SCy Schubert case -1 : 181941edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 182041edb306SCy Schubert syslog(LOG_CRIT, "read: %m\n"); 182141edb306SCy Schubert else { 182241edb306SCy Schubert ipferror(l->fd, "read"); 182341edb306SCy Schubert } 18242582ae57SCy Schubert return (0); 182541edb306SCy Schubert case 1 : 182641edb306SCy Schubert if (ipmonopts & IPMON_SYSLOG) 182741edb306SCy Schubert syslog(LOG_CRIT, "aborting logging\n"); 182841edb306SCy Schubert else if (conf->log != NULL) 182941edb306SCy Schubert fprintf(conf->log, "aborting logging\n"); 18302582ae57SCy Schubert return (0); 183141edb306SCy Schubert case 2 : 183241edb306SCy Schubert break; 183341edb306SCy Schubert case 0 : 183441edb306SCy Schubert nr += tr; 183541edb306SCy Schubert if (n > 0) { 183641edb306SCy Schubert print_log(conf, l, (char *)buf, n); 183741edb306SCy Schubert if (!(ipmonopts & IPMON_SYSLOG)) 183841edb306SCy Schubert fflush(conf->log); 183941edb306SCy Schubert } 184041edb306SCy Schubert break; 184141edb306SCy Schubert } 184241edb306SCy Schubert } 184341edb306SCy Schubert 184441edb306SCy Schubert if (!nr && (ipmonopts & IPMON_TAIL)) 184541edb306SCy Schubert sleep(1); 184641edb306SCy Schubert 18472582ae57SCy Schubert return (1); 184841edb306SCy Schubert } 1849