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