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