xref: /openbsd-src/usr.sbin/tcpdump/pf_print_state.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
1 /*	$OpenBSD: pf_print_state.c,v 1.12 2015/01/20 18:26:58 deraadt 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 <net/pfvar.h>
40 #include <arpa/inet.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 #include "addrtoname.h"
49 
50 void	print_name(struct pf_addr *, sa_family_t);
51 
52 void
53 print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose)
54 {
55 	switch (addr->type) {
56 	case PF_ADDR_DYNIFTL:
57 		printf("(%s", addr->v.ifname);
58 		if (addr->iflags & PFI_AFLAG_NETWORK)
59 			printf(":network");
60 		if (addr->iflags & PFI_AFLAG_BROADCAST)
61 			printf(":broadcast");
62 		if (addr->iflags & PFI_AFLAG_PEER)
63 			printf(":peer");
64 		if (addr->iflags & PFI_AFLAG_NOALIAS)
65 			printf(":0");
66 		if (verbose) {
67 			if (addr->p.dyncnt <= 0)
68 				printf(":*");
69 			else
70 				printf(":%d", addr->p.dyncnt);
71 		}
72 		printf(")");
73 		break;
74 	case PF_ADDR_TABLE:
75 		if (verbose)
76 			if (addr->p.tblcnt == -1)
77 				printf("<%s:*>", addr->v.tblname);
78 			else
79 				printf("<%s:%d>", addr->v.tblname,
80 				    addr->p.tblcnt);
81 		else
82 			printf("<%s>", addr->v.tblname);
83 		return;
84 	case PF_ADDR_ADDRMASK:
85 		if (PF_AZERO(&addr->v.a.addr, AF_INET6) &&
86 		    PF_AZERO(&addr->v.a.mask, AF_INET6))
87 			printf("any");
88 		else {
89 			char buf[48];
90 
91 			if (inet_ntop(af, &addr->v.a.addr, buf,
92 			    sizeof(buf)) == NULL)
93 				printf("?");
94 			else
95 				printf("%s", buf);
96 		}
97 		break;
98 	case PF_ADDR_NOROUTE:
99 		printf("no-route");
100 		return;
101 	default:
102 		printf("?");
103 		return;
104 	}
105 	if (! PF_AZERO(&addr->v.a.mask, af)) {
106 		int bits = unmask(&addr->v.a.mask, af);
107 
108 		if (bits != (af == AF_INET ? 32 : 128))
109 			printf("/%d", bits);
110 	}
111 }
112 
113 void
114 print_name(struct pf_addr *addr, sa_family_t af)
115 {
116 	char *host;
117 
118 	switch (af) {
119 	case AF_INET:
120 		host = getname((char *)&addr->v4);
121 		break;
122 	case AF_INET6:
123 		host = getname6((char *)&addr->v6);
124 		break;
125 	default:
126 		host = "?";
127 		break;
128 	}
129 	printf("%s", host);
130 }
131 
132 void
133 print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, u_int16_t rdom,
134     const char *proto, int opts)
135 {
136 	struct servent	*s = NULL;
137 	char		ps[6];
138 
139 	if (rdom)
140 		printf("(%u) ", ntohs(rdom));
141 
142 	if (opts & PF_OPT_USEDNS)
143 		print_name(addr, af);
144 	else {
145 		struct pf_addr_wrap aw;
146 
147 		memset(&aw, 0, sizeof(aw));
148 		aw.v.a.addr = *addr;
149 		if (af == AF_INET)
150 			aw.v.a.mask.addr32[0] = 0xffffffff;
151 		else {
152 			memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
153 			af = AF_INET6;
154 		}
155 		print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
156 	}
157 
158 	if (port) {
159 		snprintf(ps, sizeof(ps), "%u", ntohs(port));
160 		if (opts & PF_OPT_PORTNAMES)
161 			s = getservbyport(port, proto);
162 		if (af == AF_INET)
163 			printf(":%s", s ? s->s_name : ps);
164 		else
165 			printf("[%s]", s ? s->s_name : ps);
166 	}
167 }
168 
169 void
170 print_seq(struct pfsync_state_peer *p)
171 {
172 	if (p->seqdiff)
173 		printf("[%u + %u](+%u)", ntohl(p->seqlo),
174 		    ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff));
175 	else
176 		printf("[%u + %u]", ntohl(p->seqlo),
177 		    ntohl(p->seqhi) - ntohl(p->seqlo));
178 }
179 
180 void
181 print_state(struct pfsync_state *s, int opts)
182 {
183 	struct pfsync_state_peer *src, *dst;
184 	struct pfsync_state_key *sk, *nk;
185 	int min, sec, sidx, didx;
186 
187 	if (s->direction == PF_OUT) {
188 		src = &s->src;
189 		dst = &s->dst;
190 		sk = &s->key[PF_SK_STACK];
191 		nk = &s->key[PF_SK_WIRE];
192 		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
193 			sk->port[0] = nk->port[0];
194 	} else {
195 		src = &s->dst;
196 		dst = &s->src;
197 		sk = &s->key[PF_SK_WIRE];
198 		nk = &s->key[PF_SK_STACK];
199 		if (s->proto == IPPROTO_ICMP || s->proto == IPPROTO_ICMPV6)
200 			sk->port[1] = nk->port[1];
201 	}
202 	printf("%s ", s->ifname);
203 	printf("%s ", ipproto_string(s->proto));
204 
205 	if (nk->af != sk->af)
206 		sidx = 1, didx = 0;
207 	else
208 		sidx = 0, didx = 1;
209 
210 	print_host(&nk->addr[didx], nk->port[didx], nk->af, nk->rdomain, NULL, opts);
211 	if (nk->af != sk->af || PF_ANEQ(&nk->addr[1], &sk->addr[1], nk->af) ||
212 	    nk->port[1] != sk->port[1]) {
213 		printf(" (");
214 		print_host(&sk->addr[1], sk->port[1], sk->af, sk->rdomain,
215 		    NULL, opts);
216 		printf(")");
217 	}
218 	if (s->direction == PF_OUT)
219 		printf(" -> ");
220 	else
221 		printf(" <- ");
222 	print_host(&nk->addr[sidx], nk->port[sidx], nk->af, nk->rdomain, NULL,
223 	    opts);
224 	if (nk->af != sk->af || PF_ANEQ(&nk->addr[0], &sk->addr[0], nk->af) ||
225 	    nk->port[0] != sk->port[0]) {
226 		printf(" (");
227 		print_host(&sk->addr[0], sk->port[0], sk->af, sk->rdomain, NULL,
228 		    opts);
229 		printf(")");
230 	}
231 
232 	printf("    ");
233 	if (s->proto == IPPROTO_TCP) {
234 		if (src->state <= TCPS_TIME_WAIT &&
235 		    dst->state <= TCPS_TIME_WAIT)
236 			printf("\n   %s:%s", tcpstates[src->state],
237 			    tcpstates[dst->state]);
238 		else if (src->state == PF_TCPS_PROXY_SRC ||
239 		    dst->state == PF_TCPS_PROXY_SRC)
240 			printf("\n   PROXY:SRC");
241 		else if (src->state == PF_TCPS_PROXY_DST ||
242 		    dst->state == PF_TCPS_PROXY_DST)
243 			printf("\n   PROXY:DST");
244 		else
245 			printf("\n   <BAD STATE LEVELS %u:%u>",
246 			    src->state, dst->state);
247 		if (opts & PF_OPT_VERBOSE) {
248 			printf("\n   ");
249 			print_seq(src);
250 			if (src->wscale && dst->wscale)
251 				printf(" wscale %u",
252 				    src->wscale & PF_WSCALE_MASK);
253 			printf("  ");
254 			print_seq(dst);
255 			if (src->wscale && dst->wscale)
256 				printf(" wscale %u",
257 				    dst->wscale & PF_WSCALE_MASK);
258 		}
259 	} else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
260 	    dst->state < PFUDPS_NSTATES) {
261 		const char *states[] = PFUDPS_NAMES;
262 
263 		printf("   %s:%s", states[src->state], states[dst->state]);
264 	} else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
265 	    dst->state < PFOTHERS_NSTATES) {
266 		/* XXX ICMP doesn't really have state levels */
267 		const char *states[] = PFOTHERS_NAMES;
268 
269 		printf("   %s:%s", states[src->state], states[dst->state]);
270 	} else {
271 		printf("   %u:%u", src->state, dst->state);
272 	}
273 
274 	if (opts & PF_OPT_VERBOSE) {
275 		u_int64_t packets[2];
276 		u_int64_t bytes[2];
277 		u_int32_t creation = ntohl(s->creation);
278 		u_int32_t expire = ntohl(s->expire);
279 
280 		sec = creation % 60;
281 		creation /= 60;
282 		min = creation % 60;
283 		creation /= 60;
284 		printf("\n   age %.2u:%.2u:%.2u", creation, min, sec);
285 		sec = expire % 60;
286 		expire /= 60;
287 		min = expire % 60;
288 		expire /= 60;
289 		printf(", expires in %.2u:%.2u:%.2u", expire, min, sec);
290 
291 		bcopy(s->packets[0], &packets[0], sizeof(u_int64_t));
292 		bcopy(s->packets[1], &packets[1], sizeof(u_int64_t));
293 		bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t));
294 		bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t));
295 		printf(", %llu:%llu pkts, %llu:%llu bytes",
296 		    betoh64(packets[0]),
297 		    betoh64(packets[1]),
298 		    betoh64(bytes[0]),
299 		    betoh64(bytes[1]));
300 		if (s->anchor != -1)
301 			printf(", anchor %u", ntohl(s->anchor));
302 		if (s->rule != -1)
303 			printf(", rule %u", ntohl(s->rule));
304 	}
305 	if (opts & PF_OPT_VERBOSE2) {
306 		u_int64_t id;
307 
308 		bcopy(&s->id, &id, sizeof(u_int64_t));
309 		printf("\n   id: %016llx creatorid: %08x",
310 		    betoh64(id), ntohl(s->creatorid));
311 	}
312 }
313 
314 int
315 unmask(struct pf_addr *m, sa_family_t af)
316 {
317 	int i = 31, j = 0, b = 0;
318 	u_int32_t tmp;
319 
320 	while (j < 4 && m->addr32[j] == 0xffffffff) {
321 		b += 32;
322 		j++;
323 	}
324 	if (j < 4) {
325 		tmp = ntohl(m->addr32[j]);
326 		for (i = 31; tmp & (1 << i); --i)
327 			b++;
328 	}
329 	return (b);
330 }
331