pf_print_state.c revision 1.5
1/* $OpenBSD: pf_print_state.c,v 1.5 2008/05/09 11:57:52 mpf 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 <net/if.h> 36#define TCPSTATES 37#include <netinet/tcp_fsm.h> 38#include <net/pfvar.h> 39#include <arpa/inet.h> 40#include <netdb.h> 41 42#include <stdio.h> 43#include <string.h> 44 45#include "pfctl_parser.h" 46#include "pfctl.h" 47#include "addrtoname.h" 48 49void print_name(struct pf_addr *, sa_family_t); 50 51void 52print_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 default: 101 printf("?"); 102 return; 103 } 104 if (! PF_AZERO(&addr->v.a.mask, af)) { 105 int bits = unmask(&addr->v.a.mask, af); 106 107 if (bits != (af == AF_INET ? 32 : 128)) 108 printf("/%d", bits); 109 } 110} 111 112void 113print_name(struct pf_addr *addr, sa_family_t af) 114{ 115 char *host; 116 117 switch (af) { 118 case AF_INET: 119 host = getname((char *)&addr->v4); 120 break; 121 case AF_INET6: 122 host = getname6((char *)&addr->v6); 123 break; 124 default: 125 host = "?"; 126 break; 127 } 128 printf("%s", host); 129} 130 131void 132print_host(struct pfsync_state_host *h, sa_family_t af, int opts) 133{ 134 u_int16_t p = ntohs(h->port); 135 136 if (opts & PF_OPT_USEDNS) 137 print_name(&h->addr, af); 138 else { 139 struct pf_addr_wrap aw; 140 141 memset(&aw, 0, sizeof(aw)); 142 aw.v.a.addr = h->addr; 143 if (af == AF_INET) 144 aw.v.a.mask.addr32[0] = 0xffffffff; 145 else { 146 memset(&aw.v.a.mask, 0xff, sizeof(aw.v.a.mask)); 147 af = AF_INET6; 148 } 149 print_addr(&aw, af, opts & PF_OPT_VERBOSE2); 150 } 151 152 if (p) { 153 if (af == AF_INET) 154 printf(":%u", p); 155 else 156 printf("[%u]", p); 157 } 158} 159 160void 161print_seq(struct pfsync_state_peer *p) 162{ 163 if (p->seqdiff) 164 printf("[%u + %u](+%u)", ntohl(p->seqlo), 165 ntohl(p->seqhi) - ntohl(p->seqlo), ntohl(p->seqdiff)); 166 else 167 printf("[%u + %u]", ntohl(p->seqlo), 168 ntohl(p->seqhi) - ntohl(p->seqlo)); 169} 170 171void 172print_state(struct pfsync_state *s, int opts) 173{ 174 struct pfsync_state_peer *src, *dst; 175 int min, sec; 176 177 if (s->direction == PF_OUT) { 178 src = &s->src; 179 dst = &s->dst; 180 } else { 181 src = &s->dst; 182 dst = &s->src; 183 } 184 printf("%s ", s->ifname); 185 printf("%s ", ipproto_string(s->proto)); 186 if (PF_ANEQ(&s->lan.addr, &s->gwy.addr, s->af) || 187 (s->lan.port != s->gwy.port)) { 188 print_host(&s->lan, s->af, opts); 189 if (s->direction == PF_OUT) 190 printf(" -> "); 191 else 192 printf(" <- "); 193 } 194 print_host(&s->gwy, s->af, opts); 195 if (s->direction == PF_OUT) 196 printf(" -> "); 197 else 198 printf(" <- "); 199 print_host(&s->ext, s->af, opts); 200 201 printf(" "); 202 if (s->proto == IPPROTO_TCP) { 203 if (src->state <= TCPS_TIME_WAIT && 204 dst->state <= TCPS_TIME_WAIT) 205 printf("\n %s:%s", tcpstates[src->state], 206 tcpstates[dst->state]); 207 else if (src->state == PF_TCPS_PROXY_SRC || 208 dst->state == PF_TCPS_PROXY_SRC) 209 printf("\n PROXY:SRC"); 210 else if (src->state == PF_TCPS_PROXY_DST || 211 dst->state == PF_TCPS_PROXY_DST) 212 printf("\n PROXY:DST"); 213 else 214 printf("\n <BAD STATE LEVELS %u:%u>", 215 src->state, dst->state); 216 if (opts & PF_OPT_VERBOSE) { 217 printf("\n "); 218 print_seq(src); 219 if (src->wscale && dst->wscale) 220 printf(" wscale %u", 221 src->wscale & PF_WSCALE_MASK); 222 printf(" "); 223 print_seq(dst); 224 if (src->wscale && dst->wscale) 225 printf(" wscale %u", 226 dst->wscale & PF_WSCALE_MASK); 227 } 228 } else if (s->proto == IPPROTO_UDP && src->state < PFUDPS_NSTATES && 229 dst->state < PFUDPS_NSTATES) { 230 const char *states[] = PFUDPS_NAMES; 231 232 printf(" %s:%s", states[src->state], states[dst->state]); 233 } else if (s->proto != IPPROTO_ICMP && src->state < PFOTHERS_NSTATES && 234 dst->state < PFOTHERS_NSTATES) { 235 /* XXX ICMP doesn't really have state levels */ 236 const char *states[] = PFOTHERS_NAMES; 237 238 printf(" %s:%s", states[src->state], states[dst->state]); 239 } else { 240 printf(" %u:%u", src->state, dst->state); 241 } 242 243 if (opts & PF_OPT_VERBOSE) { 244 u_int64_t packets[2]; 245 u_int64_t bytes[2]; 246 u_int32_t creation = ntohl(s->creation); 247 248 sec = creation % 60; 249 creation /= 60; 250 min = creation % 60; 251 creation /= 60; 252 printf("\n age %.2u:%.2u:%.2u", creation, min, sec); 253 sec = s->expire % 60; 254 s->expire /= 60; 255 min = s->expire % 60; 256 s->expire /= 60; 257 printf(", expires in %.2u:%.2u:%.2u", 258 ntohl(s->expire), min, sec); 259 260 bcopy(s->packets[0], &packets[0], sizeof(u_int64_t)); 261 bcopy(s->packets[1], &packets[1], sizeof(u_int64_t)); 262 bcopy(s->bytes[0], &bytes[0], sizeof(u_int64_t)); 263 bcopy(s->bytes[1], &bytes[1], sizeof(u_int64_t)); 264 printf(", %llu:%llu pkts, %llu:%llu bytes", 265 betoh64(packets[0]), 266 betoh64(packets[1]), 267 betoh64(bytes[0]), 268 betoh64(bytes[1])); 269 if (s->anchor != -1) 270 printf(", anchor %u", ntohl(s->anchor)); 271 if (s->rule != -1) 272 printf(", rule %u", ntohl(s->rule)); 273 } 274 if (opts & PF_OPT_VERBOSE2) { 275 u_int64_t id; 276 277 bcopy(&s->id, &id, sizeof(u_int64_t)); 278 printf("\n id: %016llx creatorid: %08x", 279 betoh64(id), ntohl(s->creatorid)); 280 } 281} 282 283int 284unmask(struct pf_addr *m, sa_family_t af) 285{ 286 int i = 31, j = 0, b = 0; 287 u_int32_t tmp; 288 289 while (j < 4 && m->addr32[j] == 0xffffffff) { 290 b += 32; 291 j++; 292 } 293 if (j < 4) { 294 tmp = ntohl(m->addr32[j]); 295 for (i = 31; tmp & (1 << i); --i) 296 b++; 297 } 298 return (b); 299} 300