]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/pf/pfctl/pf_print_state.c
Import pf userland from OpenBSD 4.1 and (for ftp-proxy) libevent 1.3b as
[FreeBSD/FreeBSD.git] / contrib / pf / pfctl / pf_print_state.c
1 /*      $OpenBSD: pf_print_state.c,v 1.44 2007/03/01 17:20:53 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/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_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 (!(PF_AZERO(&addr->v.a.addr, AF_INET6) &&
112             PF_AZERO(&addr->v.a.mask, AF_INET6))) {
113                 int bits = unmask(&addr->v.a.mask, af);
114
115                 if (bits != (af == AF_INET ? 32 : 128))
116                         printf("/%d", bits);
117         }
118 }
119
120 void
121 print_name(struct pf_addr *addr, sa_family_t af)
122 {
123         char host[NI_MAXHOST];
124
125         strlcpy(host, "?", sizeof(host));
126         switch (af) {
127         case AF_INET: {
128                 struct sockaddr_in sin;
129
130                 memset(&sin, 0, sizeof(sin));
131                 sin.sin_len = sizeof(sin);
132                 sin.sin_family = AF_INET;
133                 sin.sin_addr = addr->v4;
134                 getnameinfo((struct sockaddr *)&sin, sin.sin_len,
135                     host, sizeof(host), NULL, 0, NI_NOFQDN);
136                 break;
137         }
138         case AF_INET6: {
139                 struct sockaddr_in6 sin6;
140
141                 memset(&sin6, 0, sizeof(sin6));
142                 sin6.sin6_len = sizeof(sin6);
143                 sin6.sin6_family = AF_INET6;
144                 sin6.sin6_addr = addr->v6;
145                 getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
146                     host, sizeof(host), NULL, 0, NI_NOFQDN);
147                 break;
148         }
149         }
150         printf("%s", host);
151 }
152
153 void
154 print_host(struct pf_state_host *h, sa_family_t af, int opts)
155 {
156         u_int16_t p = ntohs(h->port);
157
158         if (opts & PF_OPT_USEDNS)
159                 print_name(&h->addr, af);
160         else {
161                 struct pf_addr_wrap aw;
162
163                 memset(&aw, 0, sizeof(aw));
164                 aw.v.a.addr = h->addr;
165                 if (af == AF_INET)
166                         aw.v.a.mask.addr32[0] = 0xffffffff;
167                 else {
168                         memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask));
169                         af = AF_INET6;
170                 }
171                 print_addr(&aw, af, opts & PF_OPT_VERBOSE2);
172         }
173
174         if (p) {
175                 if (af == AF_INET)
176                         printf(":%u", p);
177                 else
178                         printf("[%u]", p);
179         }
180 }
181
182 void
183 print_seq(struct pf_state_peer *p)
184 {
185         if (p->seqdiff)
186                 printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo,
187                     p->seqdiff);
188         else
189                 printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo);
190 }
191
192 void
193 print_state(struct pf_state *s, int opts)
194 {
195         struct pf_state_peer *src, *dst;
196         struct protoent *p;
197         int min, sec;
198
199         if (s->direction == PF_OUT) {
200                 src = &s->src;
201                 dst = &s->dst;
202         } else {
203                 src = &s->dst;
204                 dst = &s->src;
205         }
206         printf("%s ", s->u.ifname);
207         if ((p = getprotobynumber(s->proto)) != NULL)
208                 printf("%s ", p->p_name);
209         else
210                 printf("%u ", s->proto);
211         if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) ||
212             (s->lan.port != s->gwy.port)) {
213                 print_host(&s->lan, s->af, opts);
214                 if (s->direction == PF_OUT)
215                         printf(" -> ");
216                 else
217                         printf(" <- ");
218         }
219         print_host(&s->gwy, s->af, opts);
220         if (s->direction == PF_OUT)
221                 printf(" -> ");
222         else
223                 printf(" <- ");
224         print_host(&s->ext, s->af, opts);
225
226         printf("    ");
227         if (s->proto == IPPROTO_TCP) {
228                 if (src->state <= TCPS_TIME_WAIT &&
229                     dst->state <= TCPS_TIME_WAIT)
230                         printf("   %s:%s\n", tcpstates[src->state],
231                             tcpstates[dst->state]);
232                 else if (src->state == PF_TCPS_PROXY_SRC ||
233                     dst->state == PF_TCPS_PROXY_SRC)
234                         printf("   PROXY:SRC\n");
235                 else if (src->state == PF_TCPS_PROXY_DST ||
236                     dst->state == PF_TCPS_PROXY_DST)
237                         printf("   PROXY:DST\n");
238                 else
239                         printf("   <BAD STATE LEVELS %u:%u>\n",
240                             src->state, dst->state);
241                 if (opts & PF_OPT_VERBOSE) {
242                         printf("   ");
243                         print_seq(src);
244                         if (src->wscale && dst->wscale)
245                                 printf(" wscale %u",
246                                     src->wscale & PF_WSCALE_MASK);
247                         printf("  ");
248                         print_seq(dst);
249                         if (src->wscale && dst->wscale)
250                                 printf(" wscale %u",
251                                     dst->wscale & PF_WSCALE_MASK);
252                         printf("\n");
253                 }
254         } else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES &&
255             dst->state < PFUDPS_NSTATES) {
256                 const char *states[] = PFUDPS_NAMES;
257
258                 printf("   %s:%s\n", states[src->state], states[dst->state]);
259         } else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES &&
260             dst->state < PFOTHERS_NSTATES) {
261                 /* XXX ICMP doesn't really have state levels */
262                 const char *states[] = PFOTHERS_NAMES;
263
264                 printf("   %s:%s\n", states[src->state], states[dst->state]);
265         } else {
266                 printf("   %u:%u\n", src->state, dst->state);
267         }
268
269         if (opts & PF_OPT_VERBOSE) {
270                 sec = s->creation % 60;
271                 s->creation /= 60;
272                 min = s->creation % 60;
273                 s->creation /= 60;
274                 printf("   age %.2u:%.2u:%.2u", s->creation, min, sec);
275                 sec = s->expire % 60;
276                 s->expire /= 60;
277                 min = s->expire % 60;
278                 s->expire /= 60;
279                 printf(", expires in %.2u:%.2u:%.2u", s->expire, min, sec);
280                 printf(", %llu:%llu pkts, %llu:%llu bytes",
281                     s->packets[0], s->packets[1], s->bytes[0], s->bytes[1]);
282                 if (s->anchor.nr != -1)
283                         printf(", anchor %u", s->anchor.nr);
284                 if (s->rule.nr != -1)
285                         printf(", rule %u", s->rule.nr);
286                 if (s->src_node != NULL)
287                         printf(", source-track");
288                 if (s->nat_src_node != NULL)
289                         printf(", sticky-address");
290                 printf("\n");
291         }
292         if (opts & PF_OPT_VERBOSE2) {
293                 printf("   id: %016llx creatorid: %08x%s\n",
294                     betoh64(s->id), ntohl(s->creatorid),
295                     ((s->sync_flags & PFSTATE_NOSYNC) ? " (no-sync)" : ""));
296         }
297 }
298
299 int
300 unmask(struct pf_addr *m, sa_family_t af)
301 {
302         int i = 31, j = 0, b = 0;
303         u_int32_t tmp;
304
305         while (j < 4 && m->addr32[j] == 0xffffffff) {
306                 b += 32;
307                 j++;
308         }
309         if (j < 4) {
310                 tmp = ntohl(m->addr32[j]);
311                 for (i = 31; tmp & (1 << i); --i)
312                         b++;
313         }
314         return (b);
315 }