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