Home | History | Annotate | Line # | Download | only in pfctl
      1 /*	$NetBSD: pf_print_state.c,v 1.4 2008/06/18 09:06:26 yamt 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/types.h>
     35 #include <sys/socket.h>
     36 #include <net/if.h>
     37 #define TCPSTATES
     38 #include <netinet/tcp_fsm.h>
     39 #include <net/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 host[NI_MAXHOST];
    125 
    126 	strlcpy(host, "?", sizeof(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 		    host, sizeof(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 		    host, sizeof(host), NULL, 0, NI_NOFQDN);
    148 		break;
    149 	}
    150 	}
    151 	printf("%s", 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(", %llu:%llu pkts, %llu:%llu bytes",
    282 		    (unsigned long long int)pf_state_counter_from_pfsync(s->packets[0]),
    283 		    (unsigned long long int)pf_state_counter_from_pfsync(s->packets[1]),
    284 		    (unsigned long long int)pf_state_counter_from_pfsync(s->bytes[0]),
    285 		    (unsigned long long int)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: %016llx creatorid: %08x%s\n",
    298 		    (unsigned long long int)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)
    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