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.2 2005/02/11 22:31:45 joerg Exp $ */ 3 4 /* 5 * Copyright (c) 2001 Daniel Hartmeier 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 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. 18 * 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. 31 * 32 */ 33 34 #include <sys/types.h> 35 #include <sys/endian.h> 36 #include <sys/socket.h> 37 #include <net/if.h> 38 #define TCPSTATES 39 #include <netinet/tcp_fsm.h> 40 #include <net/pf/pfvar.h> 41 #include <arpa/inet.h> 42 #include <netdb.h> 43 44 #include <stdio.h> 45 #include <string.h> 46 47 #include "pfctl_parser.h" 48 #include "pfctl.h" 49 50 void print_name(struct pf_addr *, sa_family_t); 51 52 void 53 print_addr(struct pf_addr_wrap *addr, sa_family_t af, int verbose) 54 { 55 switch (addr->type) { 56 case PF_ADDR_DYNIFTL: 57 printf("(%s", addr->v.ifname); 58 if (addr->iflags & PFI_AFLAG_NETWORK) 59 printf(":network"); 60 if (addr->iflags & PFI_AFLAG_BROADCAST) 61 printf(":broadcast"); 62 if (addr->iflags & PFI_AFLAG_PEER) 63 printf(":peer"); 64 if (addr->iflags & PFI_AFLAG_NOALIAS) 65 printf(":0"); 66 if (verbose) { 67 if (addr->p.dyncnt <= 0) 68 printf(":*"); 69 else 70 printf(":%d", addr->p.dyncnt); 71 } 72 printf(")"); 73 break; 74 case PF_ADDR_TABLE: 75 if (verbose) 76 if (addr->p.tblcnt == -1) 77 printf("<%s:*>", addr->v.tblname); 78 else 79 printf("<%s:%d>", addr->v.tblname, 80 addr->p.tblcnt); 81 else 82 printf("<%s>", addr->v.tblname); 83 return; 84 case PF_ADDR_ADDRMASK: 85 if (PF_AZERO(&addr->v.a.addr, AF_INET6) && 86 PF_AZERO(&addr->v.a.mask, AF_INET6)) 87 printf("any"); 88 else { 89 char buf[48]; 90 91 if (inet_ntop(af, &addr->v.a.addr, buf, 92 sizeof(buf)) == NULL) 93 printf("?"); 94 else 95 printf("%s", buf); 96 } 97 break; 98 case PF_ADDR_NOROUTE: 99 printf("no-route"); 100 return; 101 default: 102 printf("?"); 103 return; 104 } 105 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); 110 111 if (bits != (af == AF_INET ? 32 : 128)) 112 printf("/%d", bits); 113 } 114 } 115 116 void 117 print_name(struct pf_addr *addr, sa_family_t af) 118 { 119 char hostname[NI_MAXHOST]; 120 121 strlcpy(hostname, "?", sizeof(hostname)); 122 switch (af) { 123 case AF_INET: { 124 struct sockaddr_in loc_sin; 125 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); 132 break; 133 } 134 case AF_INET6: { 135 struct sockaddr_in6 sin6; 136 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); 143 break; 144 } 145 } 146 printf("%s", hostname); 147 } 148 149 void 150 print_host(struct pf_state_host *h, sa_family_t af, int opts) 151 { 152 u_int16_t p = ntohs(h->port); 153 154 if (opts & PF_OPT_USEDNS) 155 print_name(&h->addr, af); 156 else { 157 struct pf_addr_wrap aw; 158 159 memset(&aw, 0, sizeof(aw)); 160 aw.v.a.addr = h->addr; 161 if (af == AF_INET) 162 aw.v.a.mask.addr32[0] = 0xffffffff; 163 else { 164 memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 165 af = AF_INET6; 166 } 167 print_addr(&aw, af, opts & PF_OPT_VERBOSE2); 168 } 169 170 if (p) { 171 if (af == AF_INET) 172 printf(":%u", p); 173 else 174 printf("[%u]", p); 175 } 176 } 177 178 void 179 print_seq(struct pf_state_peer *p) 180 { 181 if (p->seqdiff) 182 printf("[%u + %u](+%u)", p->seqlo, p->seqhi - p->seqlo, 183 p->seqdiff); 184 else 185 printf("[%u + %u]", p->seqlo, p->seqhi - p->seqlo); 186 } 187 188 void 189 print_state(struct pf_state *s, int opts) 190 { 191 struct pf_state_peer *src, *dst; 192 struct protoent *p; 193 int min, sec; 194 195 if (s->direction == PF_OUT) { 196 src = &s->src; 197 dst = &s->dst; 198 } else { 199 src = &s->dst; 200 dst = &s->src; 201 } 202 printf("%s ", s->u.ifname); 203 if ((p = getprotobynumber(s->proto)) != NULL) 204 printf("%s ", p->p_name); 205 else 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) 211 printf(" -> "); 212 else 213 printf(" <- "); 214 } 215 print_host(&s->gwy, s->af, opts); 216 if (s->direction == PF_OUT) 217 printf(" -> "); 218 else 219 printf(" <- "); 220 print_host(&s->ext, s->af, opts); 221 222 printf(" "); 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"); 234 else 235 printf(" <BAD STATE LEVELS %u:%u>\n", 236 src->state, dst->state); 237 if (opts & PF_OPT_VERBOSE) { 238 printf(" "); 239 print_seq(src); 240 if (src->wscale && dst->wscale) 241 printf(" wscale %u", 242 src->wscale & PF_WSCALE_MASK); 243 printf(" "); 244 print_seq(dst); 245 if (src->wscale && dst->wscale) 246 printf(" wscale %u", 247 dst->wscale & PF_WSCALE_MASK); 248 printf("\n"); 249 } 250 } else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES && 251 dst->state < PFUDPS_NSTATES) { 252 const char *states[] = PFUDPS_NAMES; 253 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; 259 260 printf(" %s:%s\n", states[src->state], states[dst->state]); 261 } else { 262 printf(" %u:%u\n", src->state, dst->state); 263 } 264 265 if (opts & PF_OPT_VERBOSE) { 266 sec = s->creation % 60; 267 s->creation /= 60; 268 min = s->creation % 60; 269 s->creation /= 60; 270 printf(" age %.2u:%.2u:%.2u", s->creation, min, sec); 271 sec = s->expire % 60; 272 s->expire /= 60; 273 min = s->expire % 60; 274 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"); 286 printf("\n"); 287 } 288 if (opts & PF_OPT_VERBOSE2) { 289 printf(" id: %016llx creatorid: %08x\n", 290 be64toh(s->id), ntohl(s->creatorid)); 291 } 292 } 293 294 int 295 unmask(struct pf_addr *m, sa_family_t af __unused) 296 { 297 int i = 31, j = 0, b = 0; 298 u_int32_t tmp; 299 300 while (j < 4 && m->addr32[j] == 0xffffffff) { 301 b += 32; 302 j++; 303 } 304 if (j < 4) { 305 tmp = ntohl(m->addr32[j]); 306 for (i = 31; tmp & (1 << i); --i) 307 b++; 308 } 309 return (b); 310 } 311