pf_print_state.c revision 1.5
1/*	$OpenBSD: pf_print_state.c,v 1.5 2008/05/09 11:57:52 mpf Exp $	*/
2
3/*
4 * Copyright (c) 2001 Daniel Hartmeier
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 *    - Redistributions of source code must retain the above copyright
12 *      notice, this list of conditions and the following disclaimer.
13 *    - Redistributions in binary form must reproduce the above
14 *      copyright notice, this list of conditions and the following
15 *      disclaimer in the documentation and/or other materials provided
16 *      with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
28 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 */
32
33#include <sys/types.h>
34#include <sys/socket.h>
35#include <net/if.h>
36#define TCPSTATES
37#include <netinet/tcp_fsm.h>
38#include <net/pfvar.h>
39#include <arpa/inet.h>
40#include <netdb.h>
41
42#include <stdio.h>
43#include <string.h>
44
45#include "pfctl_parser.h"
46#include "pfctl.h"
47#include "addrtoname.h"
48
49void	print_name(struct pf_addr *, sa_family_t);
50
51void
52print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
53{
54	switch (addr->type) {
55	case PF_ADDR_DYNIFTL:
56		printf("(%s", addr->v.ifname);
57		if (addr->iflags & PFI_AFLAG_NETWORK)
58			printf(":network");
59		if (addr->iflags & PFI_AFLAG_BROADCAST)
60			printf(":broadcast");
61		if (addr->iflags & PFI_AFLAG_PEER)
62			printf(":peer");
63		if (addr->iflags & PFI_AFLAG_NOALIAS)
64			printf(":0");
65		if (verbose) {
66			if (addr->p.dyncnt <= 0)
67				printf(":*");
68			else
69				printf(":%d", addr->p.dyncnt);
70		}
71		printf(")");
72		break;
73	case PF_ADDR_TABLE:
74		if (verbose)
75			if (addr->p.tblcnt == -1)
76				printf("<%s:*>", addr->v.tblname);
77			else
78				printf("<%s:%d>", addr->v.tblname,
79				    addr->p.tblcnt);
80		else
81			printf("<%s>", addr->v.tblname);
82		return;
83	case PF_ADDR_ADDRMASK:
84		if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
85		    PF_AZERO(&addr->v.a.mask, AF_INET6))
86			printf("any");
87		else {
88			char buf[48];
89
90			if (inet_ntop(af, &addr->v.a.addr, buf,
91			    sizeof(buf)) == NULL)
92				printf("?");
93			else
94				printf("%s", buf);
95		}
96		break;
97	case PF_ADDR_NOROUTE:
98		printf("no-route");
99		return;
100	default:
101		printf("?");
102		return;
103	}
104	if (! PF_AZERO(&addr->v.a.mask, af)) {
105		int bits = unmask(&addr->v.a.mask, af);
106
107		if (bits != (af == AF_INET ? 32 : 128))
108			printf("/%d", bits);
109	}
110}
111
112void
113print_name(struct pf_addr *addr, sa_family_t af)
114{
115	char *host;
116
117	switch (af) {
118	case AF_INET:
119		host = getname((char *)&addr->v4);
120		break;
121	case AF_INET6:
122		host = getname6((char *)&addr->v6);
123		break;
124	default:
125		host = "?";
126		break;
127	}
128	printf("%s", host);
129}
130
131void
132print_host(struct pfsync_state_host *h, sa_family_t af, int opts)
133{
134	u_int16_t p = ntohs(h->port);
135
136	if (opts & PF_OPT_USEDNS)
137		print_name(&h->addr, af);
138	else {
139		struct pf_addr_wrap aw;
140
141		memset(&aw, 0, sizeof(aw));
142		aw.v.a.addr = h->addr;
143		if (af == AF_INET)
144			aw.v.a.mask.addr32[0] = 0xffffffff;
145		else {
146			memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
147			af = AF_INET6;
148		}
149		print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
150	}
151
152	if (p) {
153		if (af == AF_INET)
154			printf(":%u", p);
155		else
156			printf("[%u]", p);
157	}
158}
159
160void
161print_seq(struct pfsync_state_peer *p)
162{
163	if (p->seqdiff)
164		printf("[%u + %u](+%u)", ntohl(p->seqlo),
165		    ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
166	else
167		printf("[%u + %u]", ntohl(p->seqlo),
168		    ntohl(p->seqhi) - ntohl(p->seqlo));
169}
170
171void
172print_state(struct pfsync_state *s, int opts)
173{
174	struct pfsync_state_peer *src, *dst;
175	int min, sec;
176
177	if (s->direction == PF_OUT) {
178		src = &s->src;
179		dst = &s->dst;
180	} else {
181		src = &s->dst;
182		dst = &s->src;
183	}
184	printf("%s ", s->ifname);
185	printf("%s ", ipproto_string(s->proto));
186	if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
187	    (s->lan.port != s->gwy.port)) {
188		print_host(&s->lan, s->af, opts);
189		if (s->direction == PF_OUT)
190			printf(" -> ");
191		else
192			printf(" <- ");
193	}
194	print_host(&s->gwy, s->af, opts);
195	if (s->direction == PF_OUT)
196		printf(" -> ");
197	else
198		printf(" <- ");
199	print_host(&s->ext, s->af, opts);
200
201	printf("    ");
202	if (s->proto == IPPROTO_TCP) {
203		if (src->state <= TCPS_TIME_WAIT &&
204		    dst->state <= TCPS_TIME_WAIT)
205			printf("\n   %s:%s", tcpstates[src->state],
206			    tcpstates[dst->state]);
207		else if (src->state == PF_TCPS_PROXY_SRC ||
208		    dst->state == PF_TCPS_PROXY_SRC)
209			printf("\n   PROXY:SRC");
210		else if (src->state == PF_TCPS_PROXY_DST ||
211		    dst->state == PF_TCPS_PROXY_DST)
212			printf("\n   PROXY:DST");
213		else
214			printf("\n   <BAD STATE LEVELS %u:%u>",
215			    src->state, dst->state);
216		if (opts & PF_OPT_VERBOSE) {
217			printf("\n   ");
218			print_seq(src);
219			if (src->wscale && dst->wscale)
220				printf(" wscale %u",
221				    src->wscale & PF_WSCALE_MASK);
222			printf("  ");
223			print_seq(dst);
224			if (src->wscale && dst->wscale)
225				printf(" wscale %u",
226				    dst->wscale & PF_WSCALE_MASK);
227		}
228	} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
229	    dst->state < PFUDPS_NSTATES) {
230		const char *states[] = PFUDPS_NAMES;
231
232		printf("   %s:%s", states[src->state], states[dst->state]);
233	} else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
234	    dst->state < PFOTHERS_NSTATES) {
235		/* XXX ICMP doesn't really have state levels */
236		const char *states[] = PFOTHERS_NAMES;
237
238		printf("   %s:%s", states[src->state], states[dst->state]);
239	} else {
240		printf("   %u:%u", src->state, dst->state);
241	}
242
243	if (opts & PF_OPT_VERBOSE) {
244		u_int64_t packets[2];
245		u_int64_t bytes[2];
246		u_int32_t creation = ntohl(s->creation);
247
248		sec = creation % 60;
249		creation /= 60;
250		min = creation % 60;
251		creation /= 60;
252		printf("\n   age %.2u:%.2u:%.2u", creation, min, sec);
253		sec = s->expire % 60;
254		s->expire /= 60;
255		min = s->expire % 60;
256		s->expire /= 60;
257		printf(", expires in %.2u:%.2u:%.2u",
258		    ntohl(s->expire), min, sec);
259
260		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
261		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
262		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
263		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
264		printf(", %llu:%llu pkts, %llu:%llu bytes",
265		    betoh64(packets[0]),
266		    betoh64(packets[1]),
267		    betoh64(bytes[0]),
268		    betoh64(bytes[1]));
269		if (s->anchor != -1)
270			printf(", anchor %u", ntohl(s->anchor));
271		if (s->rule != -1)
272			printf(", rule %u", ntohl(s->rule));
273	}
274	if (opts & PF_OPT_VERBOSE2) {
275		u_int64_t id;
276
277		bcopy(&s->id, &id, sizeof(u_int64_t));
278		printf("\n   id: %016llx creatorid: %08x",
279		    betoh64(id), ntohl(s->creatorid));
280	}
281}
282
283int
284unmask(struct pf_addr *m, sa_family_t af)
285{
286	int i = 31, j = 0, b = 0;
287	u_int32_t tmp;
288
289	while (j < 4 && m->addr32[j] == 0xffffffff) {
290		b += 32;
291		j++;
292	}
293	if (j < 4) {
294		tmp = ntohl(m->addr32[j]);
295		for (i = 31; tmp & (1 << i); --i)
296			b++;
297	}
298	return (b);
299}
300