1/*	$FreeBSD$	*/
2
3/*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8
9#include "ipf.h"
10#include "kmem.h"
11
12
13ipstate_t *
14printstate(sp, opts, now)
15	ipstate_t *sp;
16	int opts;
17	u_long now;
18{
19	struct protoent *pr;
20	synclist_t ipsync;
21
22	if ((opts & OPT_NORESOLVE) == 0)
23		pr = getprotobynumber(sp->is_p);
24	else
25		pr = NULL;
26
27	PRINTF("%d:", sp->is_v);
28	if (pr != NULL)
29		PRINTF("%s", pr->p_name);
30	else
31		PRINTF("%d", sp->is_p);
32
33	PRINTF(" src:%s", hostname(sp->is_family, &sp->is_src.in4));
34	if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) {
35		if (sp->is_flags & IS_WSPORT)
36			PRINTF(",*");
37		else
38			PRINTF(",%d", ntohs(sp->is_sport));
39	}
40
41	PRINTF(" dst:%s", hostname(sp->is_family, &sp->is_dst.in4));
42	if (sp->is_p == IPPROTO_UDP || sp->is_p == IPPROTO_TCP) {
43		if (sp->is_flags & IS_WDPORT)
44			PRINTF(",*");
45		else
46			PRINTF(",%d", ntohs(sp->is_dport));
47	}
48
49	if (sp->is_p == IPPROTO_TCP) {
50		PRINTF(" state:%d/%d", sp->is_state[0], sp->is_state[1]);
51	}
52
53	PRINTF(" %ld", sp->is_die - now);
54	if (sp->is_phnext == NULL)
55		PRINTF(" ORPHAN");
56	if (sp->is_flags & IS_CLONE)
57		PRINTF(" CLONE");
58	putchar('\n');
59
60	if (sp->is_p == IPPROTO_TCP) {
61		PRINTF("\t%x:%x %hu<<%d:%hu<<%d\n",
62			sp->is_send, sp->is_dend,
63			sp->is_maxswin, sp->is_swinscale,
64			sp->is_maxdwin, sp->is_dwinscale);
65		if ((opts & OPT_VERBOSE) != 0) {
66			PRINTF("\tcmsk %04x smsk %04x isc %p s0 %08x/%08x\n",
67				sp->is_smsk[0], sp->is_smsk[1], sp->is_isc,
68				sp->is_s0[0], sp->is_s0[1]);
69			PRINTF("\tFWD: ISN inc %x sumd %x\n",
70				sp->is_isninc[0], sp->is_sumd[0]);
71			PRINTF("\tREV: ISN inc %x sumd %x\n",
72				sp->is_isninc[1], sp->is_sumd[1]);
73#ifdef	IPFILTER_SCAN
74			PRINTF("\tsbuf[0] [");
75			printsbuf(sp->is_sbuf[0]);
76			PRINTF("] sbuf[1] [");
77			printsbuf(sp->is_sbuf[1]);
78			PRINTF("]\n");
79#endif
80		}
81	} else if (sp->is_p == IPPROTO_GRE) {
82		PRINTF("\tcall %hx/%hx\n", ntohs(sp->is_gre.gs_call[0]),
83		       ntohs(sp->is_gre.gs_call[1]));
84	} else if (sp->is_p == IPPROTO_ICMP
85#ifdef	USE_INET6
86		 || sp->is_p == IPPROTO_ICMPV6
87#endif
88		) {
89		PRINTF("\tid %hu seq %hu type %d\n", sp->is_icmp.ici_id,
90			sp->is_icmp.ici_seq, sp->is_icmp.ici_type);
91	}
92
93#ifdef        USE_QUAD_T
94	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",
95		sp->is_pkts[0], sp->is_bytes[0],
96		sp->is_pkts[1], sp->is_bytes[1],
97		sp->is_pkts[2], sp->is_bytes[2],
98		sp->is_pkts[3], sp->is_bytes[3]);
99#else
100	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",
101		sp->is_pkts[0], sp->is_bytes[0],
102		sp->is_pkts[1], sp->is_bytes[1],
103		sp->is_pkts[2], sp->is_bytes[2],
104		sp->is_pkts[3], sp->is_bytes[3]);
105#endif
106
107	PRINTF("\ttag %u pass %#x = ", sp->is_tag, sp->is_pass);
108
109	/*
110	 * Print out bits set in the result code for the state being
111	 * kept as they would for a rule.
112	 */
113	if (FR_ISPASS(sp->is_pass)) {
114		PRINTF("pass");
115	} else if (FR_ISBLOCK(sp->is_pass)) {
116		PRINTF("block");
117		switch (sp->is_pass & FR_RETMASK)
118		{
119		case FR_RETICMP :
120			PRINTF(" return-icmp");
121			break;
122		case FR_FAKEICMP :
123			PRINTF(" return-icmp-as-dest");
124			break;
125		case FR_RETRST :
126			PRINTF(" return-rst");
127			break;
128		default :
129			break;
130		}
131	} else if ((sp->is_pass & FR_LOGMASK) == FR_LOG) {
132			PRINTF("log");
133		if (sp->is_pass & FR_LOGBODY)
134			PRINTF(" body");
135		if (sp->is_pass & FR_LOGFIRST)
136			PRINTF(" first");
137	} else if (FR_ISACCOUNT(sp->is_pass)) {
138		PRINTF("count");
139	} else if (FR_ISPREAUTH(sp->is_pass)) {
140		PRINTF("preauth");
141	} else if (FR_ISAUTH(sp->is_pass))
142		PRINTF("auth");
143
144	if (sp->is_pass & FR_OUTQUE)
145		PRINTF(" out");
146	else
147		PRINTF(" in");
148
149	if ((sp->is_pass & FR_LOG) != 0) {
150		PRINTF(" log");
151		if (sp->is_pass & FR_LOGBODY)
152			PRINTF(" body");
153		if (sp->is_pass & FR_LOGFIRST)
154			PRINTF(" first");
155		if (sp->is_pass & FR_LOGORBLOCK)
156			PRINTF(" or-block");
157	}
158	if (sp->is_pass & FR_QUICK)
159		PRINTF(" quick");
160	if (sp->is_pass & FR_KEEPFRAG)
161		PRINTF(" keep frags");
162	/* a given; no? */
163	if (sp->is_pass & FR_KEEPSTATE) {
164		PRINTF(" keep state");
165		if (sp->is_pass & (FR_STATESYNC|FR_STSTRICT|FR_STLOOSE)) {
166			PRINTF(" (");
167			if (sp->is_pass & FR_STATESYNC)
168				PRINTF(" sync");
169			if (sp->is_pass & FR_STSTRICT)
170				PRINTF(" strict");
171			if (sp->is_pass & FR_STLOOSE)
172				PRINTF(" loose");
173			PRINTF(" )");
174		}
175	}
176	PRINTF("\n");
177
178	if ((opts & OPT_VERBOSE) != 0) {
179		PRINTF("\tref %d", sp->is_ref);
180		PRINTF(" pkt_flags & %x(%x) = %x\n",
181			sp->is_flags & 0xf, sp->is_flags, sp->is_flags >> 4);
182		PRINTF("\tpkt_options & %x = %x, %x = %x \n", sp->is_optmsk[0],
183			sp->is_opt[0], sp->is_optmsk[1], sp->is_opt[1]);
184		PRINTF("\tpkt_security & %x = %x, pkt_auth & %x = %x\n",
185			sp->is_secmsk, sp->is_sec, sp->is_authmsk,
186			sp->is_auth);
187		PRINTF("\tis_flx %#x %#x %#x %#x\n", sp->is_flx[0][0],
188			sp->is_flx[0][1], sp->is_flx[1][0], sp->is_flx[1][1]);
189	}
190	PRINTF("\tinterfaces: in %s[%s", getifname(sp->is_ifp[0]),
191		sp->is_ifname[0]);
192	if (opts & OPT_DEBUG)
193		PRINTF("/%p", sp->is_ifp[0]);
194	putchar(']');
195	PRINTF(",%s[%s", getifname(sp->is_ifp[1]), sp->is_ifname[1]);
196	if (opts & OPT_DEBUG)
197		PRINTF("/%p", sp->is_ifp[1]);
198	putchar(']');
199	PRINTF(" out %s[%s", getifname(sp->is_ifp[2]), sp->is_ifname[2]);
200	if (opts & OPT_DEBUG)
201		PRINTF("/%p", sp->is_ifp[2]);
202	putchar(']');
203	PRINTF(",%s[%s", getifname(sp->is_ifp[3]), sp->is_ifname[3]);
204	if (opts & OPT_DEBUG)
205		PRINTF("/%p", sp->is_ifp[3]);
206	PRINTF("]\n");
207
208	PRINTF("\tSync status: ");
209	if (sp->is_sync != NULL) {
210		if (kmemcpy((char *)&ipsync, (u_long)sp->is_sync,
211			    sizeof(ipsync))) {
212			PRINTF("status could not be retrieved\n");
213			return NULL;
214		}
215
216		PRINTF("idx %d num %d v %d pr %d rev %d\n",
217			ipsync.sl_idx, ipsync.sl_num, ipsync.sl_v,
218			ipsync.sl_p, ipsync.sl_rev);
219	} else {
220		PRINTF("not synchronized\n");
221	}
222
223	return sp->is_next;
224}
225