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