1/*	$OpenBSD: pf_print_state.c,v 1.69 2019/02/02 15:43:18 yasuoka 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/in.h>
38#include <netinet/tcp_fsm.h>
39#include <arpa/inet.h>
40#include <net/pfvar.h>
41#include <netdb.h>
42
43#include <stdio.h>
44#include <string.h>
45
46#include "pfctl_parser.h"
47#include "pfctl.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_RANGE: {
84		print_addr_str(af, &addr->v.a.addr);
85		printf(" - ");
86		print_addr_str(af, &addr->v.a.mask);
87		break;
88	}
89	case PF_ADDR_ADDRMASK:
90		if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
91		    PF_AZERO(&addr->v.a.mask, AF_INET6))
92			printf("any");
93		else
94			print_addr_str(af, &addr->v.a.addr);
95		break;
96	case PF_ADDR_NOROUTE:
97		printf("no-route");
98		return;
99	case PF_ADDR_URPFFAILED:
100		printf("urpf-failed");
101		return;
102	case PF_ADDR_RTLABEL:
103		printf("route \"%s\"", addr->v.rtlabelname);
104		return;
105	default:
106		printf("?");
107		return;
108	}
109
110	/* mask if not _both_ address and mask are zero */
111	if (addr->type != PF_ADDR_RANGE &&
112	    !(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
113	    PF_AZERO(&addr->v.a.mask, AF_INET6))) {
114		int bits = unmask(&addr->v.a.mask);
115
116		if (bits < (af == AF_INET ? 32 : 128))
117			printf("/%d", bits);
118	}
119}
120
121void
122print_addr_str(sa_family_t af, struct pf_addr *addr)
123{
124	static char buf[48];
125
126	if (inet_ntop(af, addr, buf, sizeof(buf)) == NULL)
127		printf("?");
128	else
129		printf("%s", buf);
130}
131
132void
133print_name(struct pf_addr *addr, sa_family_t af)
134{
135	struct sockaddr_storage	 ss;
136	struct sockaddr_in	*sin;
137	struct sockaddr_in6	*sin6;
138	char			 host[NI_MAXHOST];
139
140	memset(&ss, 0, sizeof(ss));
141	ss.ss_family = af;
142	if (ss.ss_family == AF_INET) {
143		sin = (struct sockaddr_in *)&ss;
144		sin->sin_len = sizeof(*sin);
145		sin->sin_addr = addr->v4;
146	} else {
147		sin6 = (struct sockaddr_in6 *)&ss;
148		sin6->sin6_len = sizeof(*sin6);
149		sin6->sin6_addr = addr->v6;
150	}
151
152	if (getnameinfo((struct sockaddr *)&ss, ss.ss_len, host, sizeof(host),
153	    NULL, 0, NI_NOFQDN) != 0)
154		printf("?");
155	else
156		printf("%s", host);
157}
158
159void
160print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, u_int16_t rdom,
161    const char *proto, int opts)
162{
163	struct pf_addr_wrap	 aw;
164	struct servent		*s = NULL;
165	char			 ps[6];
166
167	if (rdom)
168		printf("(%u) ", ntohs(rdom));
169
170	if (opts & PF_OPT_USEDNS)
171		print_name(addr, af);
172	else {
173		memset(&aw, 0, sizeof(aw));
174		aw.v.a.addr = *addr;
175		memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
176		print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
177	}
178
179	if (port) {
180		snprintf(ps, sizeof(ps), "%u", ntohs(port));
181		if (opts & PF_OPT_PORTNAMES)
182			s = getservbyport(port, proto);
183		if (af == AF_INET)
184			printf(":%s", s ? s->s_name : ps);
185		else
186			printf("[%s]", s ? s->s_name : ps);
187	}
188}
189
190void
191print_seq(struct pfsync_state_peer *p)
192{
193	if (p->seqdiff)
194		printf("[%u + %u](+%u)", ntohl(p->seqlo),
195		    ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
196	else
197		printf("[%u + %u]", ntohl(p->seqlo),
198		    ntohl(p->seqhi) - ntohl(p->seqlo));
199}
200
201void
202print_state(struct pfsync_state *s, int opts)
203{
204	struct pfsync_state_peer *src, *dst;
205	struct pfsync_state_key *sk, *nk;
206	struct protoent *p;
207	char *pn = NULL;
208	int min, sec;
209	int afto = (s->key[PF_SK_STACK].af != s->key[PF_SK_WIRE].af);
210	int idx;
211
212	if (s->direction == PF_OUT) {
213		src = &s->src;
214		dst = &s->dst;
215		sk = &s->key[PF_SK_STACK];
216		nk = &s->key[PF_SK_WIRE];
217		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
218			sk->port[0] = nk->port[0];
219	} else {
220		src = &s->dst;
221		dst = &s->src;
222		sk = &s->key[PF_SK_WIRE];
223		nk = &s->key[PF_SK_STACK];
224		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
225			sk->port[1] = nk->port[1];
226	}
227	printf("%s ", s->ifname);
228	if ((p = getprotobynumber(s->proto)) != NULL) {
229		pn = p->p_name;
230		printf("%s ", pn);
231	} else
232		printf("%u ", s->proto);
233
234	print_host(&nk->addr[1], nk->port[1], nk->af, nk->rdomain, pn, opts);
235	if (nk->af != sk->af || PF_ANEQ(&nk->addr[1], &sk->addr[1], nk->af) ||
236	    nk->port[1] != sk->port[1] ||
237	    nk->rdomain != sk->rdomain) {
238		idx = afto ? 0 : 1;
239		printf(" (");
240		print_host(&sk->addr[idx], sk->port[idx], sk->af,
241		    sk->rdomain, pn, opts);
242		printf(")");
243	}
244	if (s->direction == PF_IN && !PF_AZERO(&s->rt_addr, sk->af)) {
245		printf(" {");
246		print_addr_str(sk->af, &s->rt_addr);
247		printf("}");
248	}
249	if (s->direction == PF_OUT || (afto && s->direction == PF_IN))
250		printf(" -> ");
251	else
252		printf(" <- ");
253	print_host(&nk->addr[0], nk->port[0], nk->af, nk->rdomain, pn, opts);
254	if (nk->af != sk->af || PF_ANEQ(&nk->addr[0], &sk->addr[0], nk->af) ||
255	    nk->port[0] != sk->port[0] ||
256	    nk->rdomain != sk->rdomain) {
257		idx = afto ? 1 : 0;
258		printf(" (");
259		print_host(&sk->addr[idx], sk->port[idx], sk->af,
260		    sk->rdomain, pn, opts);
261		printf(")");
262	}
263	if (s->direction == PF_OUT && !PF_AZERO(&s->rt_addr, nk->af)) {
264		printf(" {");
265		print_addr_str(nk->af, &s->rt_addr);
266		printf("}");
267	}
268
269	printf("    ");
270	if (s->proto == IPPROTO_TCP) {
271		if (src->state <= TCPS_TIME_WAIT &&
272		    dst->state <= TCPS_TIME_WAIT)
273			printf("   %s:%s\n", tcpstates[src->state],
274			    tcpstates[dst->state]);
275		else if (src->state == PF_TCPS_PROXY_SRC ||
276		    dst->state == PF_TCPS_PROXY_SRC)
277			printf("   PROXY:SRC\n");
278		else if (src->state == PF_TCPS_PROXY_DST ||
279		    dst->state == PF_TCPS_PROXY_DST)
280			printf("   PROXY:DST\n");
281		else
282			printf("   <BAD STATE LEVELS %u:%u>\n",
283			    src->state, dst->state);
284		if (opts & PF_OPT_VERBOSE) {
285			printf("   ");
286			print_seq(src);
287			if (src->wscale && dst->wscale)
288				printf(" wscale %u",
289				    src->wscale & PF_WSCALE_MASK);
290			printf("  ");
291			print_seq(dst);
292			if (src->wscale && dst->wscale)
293				printf(" wscale %u",
294				    dst->wscale & PF_WSCALE_MASK);
295			printf("\n");
296		}
297	} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
298	    dst->state < PFUDPS_NSTATES) {
299		const char *states[] = PFUDPS_NAMES;
300
301		printf("   %s:%s\n", states[src->state], states[dst->state]);
302	} else if (s->proto != IPPROTO_ICMP && s->proto != IPPROTO_ICMPV6 &&
303	    src->state < PFOTHERS_NSTATES && dst->state < PFOTHERS_NSTATES) {
304		/* XXX ICMP doesn't really have state levels */
305		const char *states[] = PFOTHERS_NAMES;
306
307		printf("   %s:%s\n", states[src->state], states[dst->state]);
308	} else {
309		printf("   %u:%u\n", src->state, dst->state);
310	}
311
312	if (opts & PF_OPT_VERBOSE) {
313		u_int64_t packets[2];
314		u_int64_t bytes[2];
315		u_int32_t creation = ntohl(s->creation);
316		u_int32_t expire = ntohl(s->expire);
317
318		sec = creation % 60;
319		creation /= 60;
320		min = creation % 60;
321		creation /= 60;
322		printf("   age %.2u:%.2u:%.2u", creation, min, sec);
323		sec = expire % 60;
324		expire /= 60;
325		min = expire % 60;
326		expire /= 60;
327		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
328
329		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
330		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
331		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
332		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
333		printf(", %llu:%llu pkts, %llu:%llu bytes",
334		    betoh64(packets[0]),
335		    betoh64(packets[1]),
336		    betoh64(bytes[0]),
337		    betoh64(bytes[1]));
338		if (ntohl(s->anchor) != -1)
339			printf(", anchor %u", ntohl(s->anchor));
340		if (ntohl(s->rule) != -1)
341			printf(", rule %u", ntohl(s->rule));
342		if (ntohs(s->state_flags) & PFSTATE_SLOPPY)
343			printf(", sloppy");
344		if (ntohs(s->state_flags) & PFSTATE_PFLOW)
345			printf(", pflow");
346		if (s->sync_flags & PFSYNC_FLAG_SRCNODE)
347			printf(", source-track");
348		if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE)
349			printf(", sticky-address");
350		printf("\n");
351	}
352	if (opts & PF_OPT_VERBOSE2) {
353		u_int64_t id;
354
355		bcopy(&s->id, &id, sizeof(u_int64_t));
356		printf("   id: %016llx creatorid: %08x",
357		    betoh64(id), ntohl(s->creatorid));
358		printf("\n");
359	}
360}
361
362int
363unmask(struct pf_addr *m)
364{
365	int i = 31, j = 0, b = 0;
366	u_int32_t tmp;
367
368	while (j < 4 && m->addr32[j] == 0xffffffff) {
369		b += 32;
370		j++;
371	}
372	if (j < 4) {
373		tmp = ntohl(m->addr32[j]);
374		for (i = 31; tmp & (1 << i); --i)
375			b++;
376	}
377	return (b);
378}
379