1 /* $OpenBSD: pf_print_state.c,v 1.52 2008/08/12 16:40:18 david Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 5 * 6 * Copyright (c) 2001 Daniel Hartmeier 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * - Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * - Redistributions in binary form must reproduce the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer in the documentation and/or other materials provided 18 * with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 28 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 #include <sys/cdefs.h> 36 #include <sys/types.h> 37 #include <sys/socket.h> 38 #include <sys/endian.h> 39 #include <net/if.h> 40 #define TCPSTATES 41 #include <netinet/tcp_fsm.h> 42 #include <netinet/sctp.h> 43 #include <net/pfvar.h> 44 #include <arpa/inet.h> 45 #include <netdb.h> 46 47 #include <stdint.h> 48 #include <stdio.h> 49 #include <string.h> 50 51 #include "pfctl_parser.h" 52 #include "pfctl.h" 53 54 void print_name(struct pf_addr *, sa_family_t); 55 56 void 57 print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose) 58 { 59 switch (addr->type) { 60 case PF_ADDR_DYNIFTL: 61 printf("(%s", addr->v.ifname); 62 if (addr->iflags & PFI_AFLAG_NETWORK) 63 printf(":network"); 64 if (addr->iflags & PFI_AFLAG_BROADCAST) 65 printf(":broadcast"); 66 if (addr->iflags & PFI_AFLAG_PEER) 67 printf(":peer"); 68 if (addr->iflags & PFI_AFLAG_NOALIAS) 69 printf(":0"); 70 if (verbose) { 71 if (addr->p.dyncnt <= 0) 72 printf(":*"); 73 else 74 printf(":%d", addr->p.dyncnt); 75 } 76 printf(")"); 77 break; 78 case PF_ADDR_TABLE: 79 if (verbose) 80 if (addr->p.tblcnt == -1) 81 printf("<%s:*>", addr->v.tblname); 82 else 83 printf("<%s:%d>", addr->v.tblname, 84 addr->p.tblcnt); 85 else 86 printf("<%s>", addr->v.tblname); 87 return; 88 case PF_ADDR_RANGE: { 89 char buf[48]; 90 91 if (inet_ntop(af, &addr->v.a.addr, buf, sizeof(buf)) == NULL) 92 printf("?"); 93 else 94 printf("%s", buf); 95 if (inet_ntop(af, &addr->v.a.mask, buf, sizeof(buf)) == NULL) 96 printf(" - ?"); 97 else 98 printf(" - %s", buf); 99 break; 100 } 101 case PF_ADDR_ADDRMASK: 102 if (PF_AZERO(&addr->v.a.addr, AF_INET6) && 103 PF_AZERO(&addr->v.a.mask, AF_INET6)) 104 printf("any"); 105 else { 106 char buf[48]; 107 108 if (inet_ntop(af, &addr->v.a.addr, buf, 109 sizeof(buf)) == NULL) 110 printf("?"); 111 else 112 printf("%s", buf); 113 } 114 break; 115 case PF_ADDR_NOROUTE: 116 printf("no-route"); 117 return; 118 case PF_ADDR_URPFFAILED: 119 printf("urpf-failed"); 120 return; 121 default: 122 printf("?"); 123 return; 124 } 125 126 /* mask if not _both_ address and mask are zero */ 127 if (addr->type != PF_ADDR_RANGE && 128 !(PF_AZERO(&addr->v.a.addr, AF_INET6) && 129 PF_AZERO(&addr->v.a.mask, AF_INET6))) { 130 int bits = unmask(&addr->v.a.mask, af); 131 132 if (bits != (af == AF_INET ? 32 : 128)) 133 printf("/%d", bits); 134 } 135 } 136 137 void 138 print_name(struct pf_addr *addr, sa_family_t af) 139 { 140 char host[NI_MAXHOST]; 141 142 strlcpy(host, "?", sizeof(host)); 143 switch (af) { 144 case AF_INET: { 145 struct sockaddr_in sin; 146 147 memset(&sin, 0, sizeof(sin)); 148 sin.sin_len = sizeof(sin); 149 sin.sin_family = AF_INET; 150 sin.sin_addr = addr->v4; 151 getnameinfo((struct sockaddr *)&sin, sin.sin_len, 152 host, sizeof(host), NULL, 0, NI_NOFQDN); 153 break; 154 } 155 case AF_INET6: { 156 struct sockaddr_in6 sin6; 157 158 memset(&sin6, 0, sizeof(sin6)); 159 sin6.sin6_len = sizeof(sin6); 160 sin6.sin6_family = AF_INET6; 161 sin6.sin6_addr = addr->v6; 162 getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 163 host, sizeof(host), NULL, 0, NI_NOFQDN); 164 break; 165 } 166 } 167 printf("%s", host); 168 } 169 170 void 171 print_host(struct pf_addr *addr, u_int16_t port, sa_family_t af, int opts) 172 { 173 if (opts & PF_OPT_USEDNS) 174 print_name(addr, af); 175 else { 176 struct pf_addr_wrap aw; 177 178 memset(&aw, 0, sizeof(aw)); 179 aw.v.a.addr = *addr; 180 if (af == AF_INET) 181 aw.v.a.mask.addr32[0] = 0xffffffff; 182 else { 183 memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 184 af = AF_INET6; 185 } 186 print_addr(&aw, af, opts & PF_OPT_VERBOSE2); 187 } 188 189 if (port) { 190 if (af == AF_INET) 191 printf(":%u", ntohs(port)); 192 else 193 printf("[%u]", ntohs(port)); 194 } 195 } 196 197 void 198 print_seq(struct pfctl_state_peer *p) 199 { 200 if (p->seqdiff) 201 printf("[%u + %u](+%u)", p->seqlo, 202 p->seqhi - p->seqlo, p->seqdiff); 203 else 204 printf("[%u + %u]", p->seqlo, 205 p->seqhi - p->seqlo); 206 } 207 208 209 static const char * 210 sctp_state_name(int state) 211 { 212 switch (state) { 213 case SCTP_CLOSED: 214 return ("CLOSED"); 215 case SCTP_BOUND: 216 return ("BOUND"); 217 case SCTP_LISTEN: 218 return ("LISTEN"); 219 case SCTP_COOKIE_WAIT: 220 return ("COOKIE_WAIT"); 221 case SCTP_COOKIE_ECHOED: 222 return ("COOKIE_ECHOED"); 223 case SCTP_ESTABLISHED: 224 return ("ESTABLISHED"); 225 case SCTP_SHUTDOWN_SENT: 226 return ("SHUTDOWN_SENT"); 227 case SCTP_SHUTDOWN_RECEIVED: 228 return ("SHUTDOWN_RECEIVED"); 229 case SCTP_SHUTDOWN_ACK_SENT: 230 return ("SHUTDOWN_ACK_SENT"); 231 case SCTP_SHUTDOWN_PENDING: 232 return ("SHUTDOWN_PENDING"); 233 default: 234 return ("?"); 235 } 236 } 237 238 void 239 print_state(struct pfctl_state *s, int opts) 240 { 241 struct pfctl_state_peer *src, *dst; 242 struct pfctl_state_key *key, *sk, *nk; 243 const char *protoname; 244 int min, sec; 245 sa_family_t af; 246 uint8_t proto; 247 #ifndef __NO_STRICT_ALIGNMENT 248 struct pfctl_state_key aligned_key[2]; 249 250 bcopy(&s->key, aligned_key, sizeof(aligned_key)); 251 key = aligned_key; 252 #else 253 key = s->key; 254 #endif 255 256 af = s->key[PF_SK_WIRE].af; 257 proto = s->key[PF_SK_WIRE].proto; 258 259 if (s->direction == PF_OUT) { 260 src = &s->src; 261 dst = &s->dst; 262 sk = &key[PF_SK_STACK]; 263 nk = &key[PF_SK_WIRE]; 264 if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) 265 sk->port[0] = nk->port[0]; 266 } else { 267 src = &s->dst; 268 dst = &s->src; 269 sk = &key[PF_SK_WIRE]; 270 nk = &key[PF_SK_STACK]; 271 if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6) 272 sk->port[1] = nk->port[1]; 273 } 274 printf("%s ", s->ifname); 275 if ((protoname = pfctl_proto2name(proto)) != NULL) 276 printf("%s ", protoname); 277 else 278 printf("%u ", proto); 279 280 print_host(&nk->addr[1], nk->port[1], af, opts); 281 if (PF_ANEQ(&nk->addr[1], &sk->addr[1], af) || 282 nk->port[1] != sk->port[1]) { 283 printf(" ("); 284 print_host(&sk->addr[1], sk->port[1], af, opts); 285 printf(")"); 286 } 287 if (s->direction == PF_OUT) 288 printf(" -> "); 289 else 290 printf(" <- "); 291 print_host(&nk->addr[0], nk->port[0], af, opts); 292 if (PF_ANEQ(&nk->addr[0], &sk->addr[0], af) || 293 nk->port[0] != sk->port[0]) { 294 printf(" ("); 295 print_host(&sk->addr[0], sk->port[0], af, opts); 296 printf(")"); 297 } 298 299 printf(" "); 300 if (proto == IPPROTO_TCP) { 301 if (src->state <= TCPS_TIME_WAIT && 302 dst->state <= TCPS_TIME_WAIT) 303 printf(" %s:%s\n", tcpstates[src->state], 304 tcpstates[dst->state]); 305 else if (src->state == PF_TCPS_PROXY_SRC || 306 dst->state == PF_TCPS_PROXY_SRC) 307 printf(" PROXY:SRC\n"); 308 else if (src->state == PF_TCPS_PROXY_DST || 309 dst->state == PF_TCPS_PROXY_DST) 310 printf(" PROXY:DST\n"); 311 else 312 printf(" <BAD STATE LEVELS %u:%u>\n", 313 src->state, dst->state); 314 if (opts & PF_OPT_VERBOSE) { 315 printf(" "); 316 print_seq(src); 317 if (src->wscale && dst->wscale) 318 printf(" wscale %u", 319 src->wscale & PF_WSCALE_MASK); 320 printf(" "); 321 print_seq(dst); 322 if (src->wscale && dst->wscale) 323 printf(" wscale %u", 324 dst->wscale & PF_WSCALE_MASK); 325 printf("\n"); 326 } 327 } else if (proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES && 328 dst->state < PFUDPS_NSTATES) { 329 const char *states[] = PFUDPS_NAMES; 330 331 printf(" %s:%s\n", states[src->state], states[dst->state]); 332 } else if (proto == IPPROTO_SCTP) { 333 printf(" %s:%s\n", sctp_state_name(src->state), 334 sctp_state_name(dst->state)); 335 #ifndef INET6 336 } else if (proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES && 337 dst->state < PFOTHERS_NSTATES) { 338 #else 339 } else if (proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6 && 340 src->state < PFOTHERS_NSTATES && dst->state < PFOTHERS_NSTATES) { 341 #endif 342 /* XXX ICMP doesn't really have state levels */ 343 const char *states[] = PFOTHERS_NAMES; 344 345 printf(" %s:%s\n", states[src->state], states[dst->state]); 346 } else { 347 printf(" %u:%u\n", src->state, dst->state); 348 } 349 350 if (opts & PF_OPT_VERBOSE) { 351 u_int32_t creation = s->creation; 352 u_int32_t expire = s->expire; 353 354 sec = creation % 60; 355 creation /= 60; 356 min = creation % 60; 357 creation /= 60; 358 printf(" age %.2u:%.2u:%.2u", creation, min, sec); 359 sec = expire % 60; 360 expire /= 60; 361 min = expire % 60; 362 expire /= 60; 363 printf(", expires in %.2u:%.2u:%.2u", expire, min, sec); 364 365 printf(", %ju:%ju pkts, %ju:%ju bytes", 366 s->packets[0], 367 s->packets[1], 368 s->bytes[0], 369 s->bytes[1]); 370 if (s->anchor != -1) 371 printf(", anchor %u", s->anchor); 372 if (s->rule != -1) 373 printf(", rule %u", s->rule); 374 if (s->state_flags & PFSTATE_ALLOWOPTS) 375 printf(", allow-opts"); 376 if (s->state_flags & PFSTATE_SLOPPY) 377 printf(", sloppy"); 378 if (s->state_flags & PFSTATE_NOSYNC) 379 printf(", no-sync"); 380 if (s->state_flags & PFSTATE_ACK) 381 printf(", psync-ack"); 382 if (s->state_flags & PFSTATE_NODF) 383 printf(", no-df"); 384 if (s->state_flags & PFSTATE_SETTOS) 385 printf(", set-tos 0x%2.2x", s->set_tos); 386 if (s->state_flags & PFSTATE_RANDOMID) 387 printf(", random-id"); 388 if (s->state_flags & PFSTATE_SCRUB_TCP) 389 printf(", reassemble-tcp"); 390 if (s->state_flags & PFSTATE_SETPRIO) 391 printf(", set-prio (0x%02x 0x%02x)", 392 s->set_prio[0], s->set_prio[1]); 393 if (s->dnpipe || s->dnrpipe) { 394 if (s->state_flags & PFSTATE_DN_IS_PIPE) 395 printf(", dummynet pipe (%d %d)", 396 s->dnpipe, s->dnrpipe); 397 if (s->state_flags & PFSTATE_DN_IS_QUEUE) 398 printf(", dummynet queue (%d %d)", 399 s->dnpipe, s->dnrpipe); 400 } 401 if (s->sync_flags & PFSYNC_FLAG_SRCNODE) 402 printf(", source-track"); 403 if (s->sync_flags & PFSYNC_FLAG_NATSRCNODE) 404 printf(", sticky-address"); 405 if (s->log) 406 printf(", log"); 407 if (s->log & PF_LOG_ALL) 408 printf(" (all)"); 409 if (s->min_ttl) 410 printf(", min-ttl %d", s->min_ttl); 411 if (s->max_mss) 412 printf(", max-mss %d", s->max_mss); 413 printf("\n"); 414 } 415 if (opts & PF_OPT_VERBOSE2) { 416 u_int64_t id; 417 418 bcopy(&s->id, &id, sizeof(u_int64_t)); 419 printf(" id: %016jx creatorid: %08x", id, s->creatorid); 420 if (s->rt) { 421 switch (s->rt) { 422 case PF_ROUTETO: 423 printf(" route-to: "); 424 break; 425 case PF_DUPTO: 426 printf(" dup-to: "); 427 break; 428 case PF_REPLYTO: 429 printf(" reply-to: "); 430 break; 431 default: 432 printf(" gateway: "); 433 } 434 print_host(&s->rt_addr, 0, af, opts); 435 if (s->rt_ifname[0]) 436 printf("@%s", s->rt_ifname); 437 } 438 if (s->rtableid != -1) 439 printf(" rtable: %d", s->rtableid); 440 printf("\n"); 441 442 if (strcmp(s->ifname, s->orig_ifname) != 0) 443 printf(" origif: %s\n", s->orig_ifname); 444 } 445 } 446 447 int 448 unmask(struct pf_addr *m, sa_family_t af) 449 { 450 int i = 31, j = 0, b = 0; 451 u_int32_t tmp; 452 453 while (j < 4 && m->addr32[j] == 0xffffffff) { 454 b += 32; 455 j++; 456 } 457 if (j < 4) { 458 tmp = ntohl(m->addr32[j]); 459 for (i = 31; tmp & (1 << i); --i) 460 b++; 461 } 462 return (b); 463 } 464