1 /* $OpenBSD: pf_print_state.c,v 1.39 2004/02/10 17:48:08 henning Exp $ */
2 /* $DragonFly: src/usr.sbin/pfctl/pf_print_state.c,v 1.3 2008/04/11 18:21:49 dillon Exp $ */
5 * Copyright (c) 2001 Daniel Hartmeier
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * - Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * - Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/types.h>
35 #include <sys/endian.h>
36 #include <sys/socket.h>
39 #include <netinet/tcp_fsm.h>
40 #include <net/pf/pfvar.h>
41 #include <arpa/inet.h>
47 #include "pfctl_parser.h"
50 void print_name(struct pf_addr
*, sa_family_t
);
53 print_addr(struct pf_addr_wrap
*addr
, sa_family_t af
, int verbose
)
57 printf("(%s", addr
->v
.ifname
);
58 if (addr
->iflags
& PFI_AFLAG_NETWORK
)
60 if (addr
->iflags
& PFI_AFLAG_BROADCAST
)
62 if (addr
->iflags
& PFI_AFLAG_PEER
)
64 if (addr
->iflags
& PFI_AFLAG_NOALIAS
)
67 if (addr
->p
.dyncnt
<= 0)
70 printf(":%d", addr
->p
.dyncnt
);
76 if (addr
->p
.tblcnt
== -1)
77 printf("<%s:*>", addr
->v
.tblname
);
79 printf("<%s:%d>", addr
->v
.tblname
,
82 printf("<%s>", addr
->v
.tblname
);
84 case PF_ADDR_ADDRMASK
:
85 if (PF_AZERO(&addr
->v
.a
.addr
, AF_INET6
) &&
86 PF_AZERO(&addr
->v
.a
.mask
, AF_INET6
))
91 if (inet_ntop(af
, &addr
->v
.a
.addr
, buf
,
106 /* mask if not _both_ address and mask are zero */
107 if (!(PF_AZERO(&addr
->v
.a
.addr
, AF_INET6
) &&
108 PF_AZERO(&addr
->v
.a
.mask
, AF_INET6
))) {
109 int bits
= unmask(&addr
->v
.a
.mask
, af
);
111 if (bits
!= (af
== AF_INET
? 32 : 128))
117 print_name(struct pf_addr
*addr
, sa_family_t af
)
119 char hostname
[NI_MAXHOST
];
121 strlcpy(hostname
, "?", sizeof(hostname
));
124 struct sockaddr_in loc_sin
;
126 memset(&loc_sin
, 0, sizeof(loc_sin
));
127 loc_sin
.sin_len
= sizeof(loc_sin
);
128 loc_sin
.sin_family
= AF_INET
;
129 loc_sin
.sin_addr
= addr
->v4
;
130 getnameinfo((struct sockaddr
*)&loc_sin
, loc_sin
.sin_len
,
131 hostname
, sizeof(hostname
), NULL
, 0, NI_NOFQDN
);
135 struct sockaddr_in6 sin6
;
137 memset(&sin6
, 0, sizeof(sin6
));
138 sin6
.sin6_len
= sizeof(sin6
);
139 sin6
.sin6_family
= AF_INET6
;
140 sin6
.sin6_addr
= addr
->v6
;
141 getnameinfo((struct sockaddr
*)&sin6
, sin6
.sin6_len
,
142 hostname
, sizeof(hostname
), NULL
, 0, NI_NOFQDN
);
146 printf("%s", hostname
);
150 print_host(struct pf_state_host
*h
, sa_family_t af
, int opts
)
152 u_int16_t p
= ntohs(h
->port
);
154 if (opts
& PF_OPT_USEDNS
)
155 print_name(&h
->addr
, af
);
157 struct pf_addr_wrap aw
;
159 memset(&aw
, 0, sizeof(aw
));
160 aw
.v
.a
.addr
= h
->addr
;
162 aw
.v
.a
.mask
.addr32
[0] = 0xffffffff;
164 memset(&aw
.v
.a
.mask
, 0xff, sizeof(aw
.v
.a
.mask
));
167 print_addr(&aw
, af
, opts
& PF_OPT_VERBOSE2
);
179 print_seq(struct pf_state_peer
*p
)
182 printf("[%u + %u](+%u)", p
->seqlo
, p
->seqhi
- p
->seqlo
,
185 printf("[%u + %u]", p
->seqlo
, p
->seqhi
- p
->seqlo
);
189 print_state(struct pf_state
*s
, int opts
)
191 struct pf_state_peer
*src
, *dst
;
195 if (s
->direction
== PF_OUT
) {
202 printf("%s ", s
->u
.ifname
);
203 if ((p
= getprotobynumber(s
->proto
)) != NULL
)
204 printf("%s ", p
->p_name
);
206 printf("%u ", s
->proto
);
207 if (PF_ANEQ(&s
->lan
.addr
, &s
->gwy
.addr
, s
->af
) ||
208 (s
->lan
.port
!= s
->gwy
.port
)) {
209 print_host(&s
->lan
, s
->af
, opts
);
210 if (s
->direction
== PF_OUT
)
215 print_host(&s
->gwy
, s
->af
, opts
);
216 if (s
->direction
== PF_OUT
)
220 print_host(&s
->ext
, s
->af
, opts
);
223 if (s
->proto
== IPPROTO_TCP
) {
224 if (src
->state
<= TCPS_TIME_WAIT
&&
225 dst
->state
<= TCPS_TIME_WAIT
)
226 printf(" %s:%s\n", tcpstates
[src
->state
],
227 tcpstates
[dst
->state
]);
228 else if (src
->state
== PF_TCPS_PROXY_SRC
||
229 dst
->state
== PF_TCPS_PROXY_SRC
)
230 printf(" PROXY:SRC\n");
231 else if (src
->state
== PF_TCPS_PROXY_DST
||
232 dst
->state
== PF_TCPS_PROXY_DST
)
233 printf(" PROXY:DST\n");
235 printf(" <BAD STATE LEVELS %u:%u>\n",
236 src
->state
, dst
->state
);
237 if (opts
& PF_OPT_VERBOSE
) {
240 if (src
->wscale
&& dst
->wscale
)
242 src
->wscale
& PF_WSCALE_MASK
);
245 if (src
->wscale
&& dst
->wscale
)
247 dst
->wscale
& PF_WSCALE_MASK
);
250 } else if (s
->proto
== IPPROTO_UDP
&& src
->state
< PFUDPS_NSTATES
&&
251 dst
->state
< PFUDPS_NSTATES
) {
252 const char *states
[] = PFUDPS_NAMES
;
254 printf(" %s:%s\n", states
[src
->state
], states
[dst
->state
]);
255 } else if (s
->proto
!= IPPROTO_ICMP
&& src
->state
< PFOTHERS_NSTATES
&&
256 dst
->state
< PFOTHERS_NSTATES
) {
257 /* XXX ICMP doesn't really have state levels */
258 const char *states
[] = PFOTHERS_NAMES
;
260 printf(" %s:%s\n", states
[src
->state
], states
[dst
->state
]);
262 printf(" %u:%u\n", src
->state
, dst
->state
);
265 if (opts
& PF_OPT_VERBOSE
) {
266 sec
= s
->creation
% 60;
268 min
= s
->creation
% 60;
270 printf(" age %.2u:%.2u:%.2u", s
->creation
, min
, sec
);
271 sec
= s
->expire
% 60;
273 min
= s
->expire
% 60;
275 printf(", expires in %.2u:%.2u:%.2u", s
->expire
, min
, sec
);
276 printf(", %u:%u pkts, %u:%u bytes",
277 s
->packets
[0], s
->packets
[1], s
->bytes
[0], s
->bytes
[1]);
278 if (s
->anchor
.nr
!= (uint32_t)(-1))
279 printf(", anchor %u", s
->anchor
.nr
);
280 if (s
->rule
.nr
!= (uint32_t)(-1))
281 printf(", rule %u", s
->rule
.nr
);
282 if (s
->src_node
!= NULL
)
283 printf(", source-track");
284 if (s
->nat_src_node
!= NULL
)
285 printf(", sticky-address");
288 if (opts
& PF_OPT_VERBOSE2
) {
289 printf(" id: %016llx creatorid: %08x",
290 (unsigned long long)be64toh(s
->id
), ntohl(s
->creatorid
));
292 printf(" synchronization: ");
293 if ((s
->sync_flags
& PFSTATE_GOT_SYN_MASK
) ==
294 PFSTATE_GOT_SYN_MASK
) {
296 } else if (s
->sync_flags
& PFSTATE_GOT_SYN_MASK
) {
297 printf("incomplete");
299 printf("indeterminate");
306 unmask(struct pf_addr
*m
, sa_family_t af __unused
)
308 int i
= 31, j
= 0, b
= 0;
311 while (j
< 4 && m
->addr32
[j
] == 0xffffffff) {
316 tmp
= ntohl(m
->addr32
[j
]);
317 for (i
= 31; tmp
& (1 << i
); --i
)