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