xref: /freebsd/sbin/ipf/ipmon/ipmon.c (revision 90f2fee0e0400a785db8e5eadad40801d77b74b8)
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(&nothingsaver);
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