1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3145510Sdarrenr/*
4255332Scy * Copyright (C) 2012 by Darren Reed.
5145510Sdarrenr *
6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145510Sdarrenr */
8145510Sdarrenr
9145510Sdarrenr#include "ipf.h"
10145510Sdarrenr#include "kmem.h"
11145510Sdarrenr
12145510Sdarrenr
13255332Scyipstate_t *
14255332Scyprintstate(sp, opts, now)
15255332Scy	ipstate_t *sp;
16255332Scy	int opts;
17255332Scy	u_long now;
18145510Sdarrenr{
19255332Scy	struct protoent *pr;
20145510Sdarrenr	synclist_t ipsync;
21145510Sdarrenr
22255332Scy	if ((opts & OPT_NORESOLVE) == 0)
23255332Scy		pr = getprotobynumber(sp->is_p);
24255332Scy	else
25255332Scy		pr = NULL;
26255332Scy
27255332Scy	PRINTF("%d:", sp->is_v);
28255332Scy	if (pr != NULL)
29255332Scy		PRINTF("%s", pr->p_name);
30255332Scy	else
31255332Scy		PRINTF("%d", sp->is_p);
32255332Scy
33255332Scy	PRINTF(" src:%s", hostname(sp->is_family, &sp->is_src.in4));
34255332Scy	if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) {
35255332Scy		if (sp->is_flags & IS_WSPORT)
36255332Scy			PRINTF(",*");
37255332Scy		else
38255332Scy			PRINTF(",%d", ntohs(sp->is_sport));
39255332Scy	}
40255332Scy
41255332Scy	PRINTF(" dst:%s", hostname(sp->is_family, &sp->is_dst.in4));
42255332Scy	if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) {
43255332Scy		if (sp->is_flags & IS_WDPORT)
44255332Scy			PRINTF(",*");
45255332Scy		else
46255332Scy			PRINTF(",%d", ntohs(sp->is_dport));
47255332Scy	}
48255332Scy
49255332Scy	if (sp->is_p == IPPROTO_TCP) {
50255332Scy		PRINTF(" state:%d/%d", sp->is_state[0], sp->is_state[1]);
51255332Scy	}
52255332Scy
53255332Scy	PRINTF(" %ld", sp->is_die - now);
54170268Sdarrenr	if (sp->is_phnext == NULL)
55255332Scy		PRINTF(" ORPHAN");
56255332Scy	if (sp->is_flags & IS_CLONE)
57255332Scy		PRINTF(" CLONE");
58255332Scy	putchar('\n');
59145510Sdarrenr
60170268Sdarrenr	if (sp->is_p == IPPROTO_TCP) {
61255332Scy		PRINTF("\t%x:%x %hu<<%d:%hu<<%d\n",
62170268Sdarrenr			sp->is_send, sp->is_dend,
63170268Sdarrenr			sp->is_maxswin, sp->is_swinscale,
64170268Sdarrenr			sp->is_maxdwin, sp->is_dwinscale);
65255332Scy		if ((opts & OPT_VERBOSE) != 0) {
66255332Scy			PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n",
67255332Scy				sp->is_smsk[0], sp->is_smsk[1], sp->is_isc,
68255332Scy				sp->is_s0[0], sp->is_s0[1]);
69255332Scy			PRINTF("\tFWD: ISN inc %x sumd %x\n",
70255332Scy				sp->is_isninc[0], sp->is_sumd[0]);
71255332Scy			PRINTF("\tREV: ISN inc %x sumd %x\n",
72255332Scy				sp->is_isninc[1], sp->is_sumd[1]);
73145510Sdarrenr#ifdef	IPFILTER_SCAN
74255332Scy			PRINTF("\tsbuf[0] [");
75255332Scy			printsbuf(sp->is_sbuf[0]);
76255332Scy			PRINTF("] sbuf[1] [");
77255332Scy			printsbuf(sp->is_sbuf[1]);
78255332Scy			PRINTF("]\n");
79145510Sdarrenr#endif
80255332Scy		}
81170268Sdarrenr	} else if (sp->is_p == IPPROTO_GRE) {
82255332Scy		PRINTF("\tcall %hx/%hx\n", ntohs(sp->is_gre.gs_call[0]),
83170268Sdarrenr		       ntohs(sp->is_gre.gs_call[1]));
84170268Sdarrenr	} else if (sp->is_p == IPPROTO_ICMP
85145510Sdarrenr#ifdef	USE_INET6
86170268Sdarrenr		 || sp->is_p == IPPROTO_ICMPV6
87145510Sdarrenr#endif
88255332Scy		) {
89255332Scy		PRINTF("\tid %hu seq %hu type %d\n", sp->is_icmp.ici_id,
90170268Sdarrenr			sp->is_icmp.ici_seq, sp->is_icmp.ici_type);
91255332Scy	}
92145510Sdarrenr
93145510Sdarrenr#ifdef        USE_QUAD_T
94255332Scy	PRINTF("\tFWD: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n\tREV: IN pkts %"PRIu64" bytes %"PRIu64" OUT pkts %"PRIu64" bytes %"PRIu64"\n",
95170268Sdarrenr		sp->is_pkts[0], sp->is_bytes[0],
96170268Sdarrenr		sp->is_pkts[1], sp->is_bytes[1],
97170268Sdarrenr		sp->is_pkts[2], sp->is_bytes[2],
98170268Sdarrenr		sp->is_pkts[3], sp->is_bytes[3]);
99145510Sdarrenr#else
100255332Scy	PRINTF("\tFWD: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n\tREV: IN pkts %lu bytes %lu OUT pkts %lu bytes %lu\n",
101170268Sdarrenr		sp->is_pkts[0], sp->is_bytes[0],
102170268Sdarrenr		sp->is_pkts[1], sp->is_bytes[1],
103170268Sdarrenr		sp->is_pkts[2], sp->is_bytes[2],
104170268Sdarrenr		sp->is_pkts[3], sp->is_bytes[3]);
105145510Sdarrenr#endif
106145510Sdarrenr
107255332Scy	PRINTF("\ttag %u pass %#x = ", sp->is_tag, sp->is_pass);
108145510Sdarrenr
109145510Sdarrenr	/*
110145510Sdarrenr	 * Print out bits set in the result code for the state being
111145510Sdarrenr	 * kept as they would for a rule.
112145510Sdarrenr	 */
113170268Sdarrenr	if (FR_ISPASS(sp->is_pass)) {
114145510Sdarrenr		PRINTF("pass");
115170268Sdarrenr	} else if (FR_ISBLOCK(sp->is_pass)) {
116145510Sdarrenr		PRINTF("block");
117170268Sdarrenr		switch (sp->is_pass & FR_RETMASK)
118145510Sdarrenr		{
119145510Sdarrenr		case FR_RETICMP :
120145510Sdarrenr			PRINTF(" return-icmp");
121145510Sdarrenr			break;
122145510Sdarrenr		case FR_FAKEICMP :
123145510Sdarrenr			PRINTF(" return-icmp-as-dest");
124145510Sdarrenr			break;
125145510Sdarrenr		case FR_RETRST :
126145510Sdarrenr			PRINTF(" return-rst");
127145510Sdarrenr			break;
128145510Sdarrenr		default :
129145510Sdarrenr			break;
130145510Sdarrenr		}
131170268Sdarrenr	} else if ((sp->is_pass & FR_LOGMASK) == FR_LOG) {
132145510Sdarrenr			PRINTF("log");
133170268Sdarrenr		if (sp->is_pass & FR_LOGBODY)
134145510Sdarrenr			PRINTF(" body");
135170268Sdarrenr		if (sp->is_pass & FR_LOGFIRST)
136145510Sdarrenr			PRINTF(" first");
137170268Sdarrenr	} else if (FR_ISACCOUNT(sp->is_pass)) {
138145510Sdarrenr		PRINTF("count");
139170268Sdarrenr	} else if (FR_ISPREAUTH(sp->is_pass)) {
140145510Sdarrenr		PRINTF("preauth");
141170268Sdarrenr	} else if (FR_ISAUTH(sp->is_pass))
142145510Sdarrenr		PRINTF("auth");
143145510Sdarrenr
144170268Sdarrenr	if (sp->is_pass & FR_OUTQUE)
145145510Sdarrenr		PRINTF(" out");
146145510Sdarrenr	else
147145510Sdarrenr		PRINTF(" in");
148145510Sdarrenr
149170268Sdarrenr	if ((sp->is_pass & FR_LOG) != 0) {
150145510Sdarrenr		PRINTF(" log");
151170268Sdarrenr		if (sp->is_pass & FR_LOGBODY)
152145510Sdarrenr			PRINTF(" body");
153170268Sdarrenr		if (sp->is_pass & FR_LOGFIRST)
154145510Sdarrenr			PRINTF(" first");
155170268Sdarrenr		if (sp->is_pass & FR_LOGORBLOCK)
156145510Sdarrenr			PRINTF(" or-block");
157145510Sdarrenr	}
158170268Sdarrenr	if (sp->is_pass & FR_QUICK)
159145510Sdarrenr		PRINTF(" quick");
160170268Sdarrenr	if (sp->is_pass & FR_KEEPFRAG)
161145510Sdarrenr		PRINTF(" keep frags");
162145510Sdarrenr	/* a given; no? */
163170268Sdarrenr	if (sp->is_pass & FR_KEEPSTATE) {
164145510Sdarrenr		PRINTF(" keep state");
165255332Scy		if (sp->is_pass & (FR_STATESYNC|FR_STSTRICT|FR_STLOOSE)) {
166255332Scy			PRINTF(" (");
167255332Scy			if (sp->is_pass & FR_STATESYNC)
168255332Scy				PRINTF(" sync");
169255332Scy			if (sp->is_pass & FR_STSTRICT)
170255332Scy				PRINTF(" strict");
171255332Scy			if (sp->is_pass & FR_STLOOSE)
172255332Scy				PRINTF(" loose");
173255332Scy			PRINTF(" )");
174255332Scy		}
175145510Sdarrenr	}
176145510Sdarrenr	PRINTF("\n");
177145510Sdarrenr
178255332Scy	if ((opts & OPT_VERBOSE) != 0) {
179255332Scy		PRINTF("\tref %d", sp->is_ref);
180255332Scy		PRINTF(" pkt_flags & %x(%x) = %x\n",
181255332Scy			sp->is_flags & 0xf, sp->is_flags, sp->is_flags >> 4);
182255332Scy		PRINTF("\tpkt_options & %x = %x, %x = %x \n", sp->is_optmsk[0],
183255332Scy			sp->is_opt[0], sp->is_optmsk[1], sp->is_opt[1]);
184255332Scy		PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n",
185255332Scy			sp->is_secmsk, sp->is_sec, sp->is_authmsk,
186255332Scy			sp->is_auth);
187255332Scy		PRINTF("\tis_flx %#x %#x %#x %#x\n", sp->is_flx[0][0],
188255332Scy			sp->is_flx[0][1], sp->is_flx[1][0], sp->is_flx[1][1]);
189255332Scy	}
190170268Sdarrenr	PRINTF("\tinterfaces: in %s[%s", getifname(sp->is_ifp[0]),
191170268Sdarrenr		sp->is_ifname[0]);
192145510Sdarrenr	if (opts & OPT_DEBUG)
193170268Sdarrenr		PRINTF("/%p", sp->is_ifp[0]);
194145510Sdarrenr	putchar(']');
195170268Sdarrenr	PRINTF(",%s[%s", getifname(sp->is_ifp[1]), sp->is_ifname[1]);
196145510Sdarrenr	if (opts & OPT_DEBUG)
197170268Sdarrenr		PRINTF("/%p", sp->is_ifp[1]);
198145510Sdarrenr	putchar(']');
199170268Sdarrenr	PRINTF(" out %s[%s", getifname(sp->is_ifp[2]), sp->is_ifname[2]);
200145510Sdarrenr	if (opts & OPT_DEBUG)
201170268Sdarrenr		PRINTF("/%p", sp->is_ifp[2]);
202145510Sdarrenr	putchar(']');
203170268Sdarrenr	PRINTF(",%s[%s", getifname(sp->is_ifp[3]), sp->is_ifname[3]);
204145510Sdarrenr	if (opts & OPT_DEBUG)
205170268Sdarrenr		PRINTF("/%p", sp->is_ifp[3]);
206145510Sdarrenr	PRINTF("]\n");
207145510Sdarrenr
208255332Scy	PRINTF("\tSync status: ");
209170268Sdarrenr	if (sp->is_sync != NULL) {
210255332Scy		if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync,
211255332Scy			    sizeof(ipsync))) {
212255332Scy			PRINTF("status could not be retrieved\n");
213145510Sdarrenr			return NULL;
214145510Sdarrenr		}
215145510Sdarrenr
216255332Scy		PRINTF("idx %d num %d v %d pr %d rev %d\n",
217145510Sdarrenr			ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v,
218145510Sdarrenr			ipsync.sl_p, ipsync.sl_rev);
219145510Sdarrenr	} else {
220255332Scy		PRINTF("not synchronized\n");
221145510Sdarrenr	}
222145510Sdarrenr
223170268Sdarrenr	return sp->is_next;
224145510Sdarrenr}
225