xref: /openbsd-src/usr.bin/systat/pftop.c (revision 0b7734b3d77bb9b21afec6f4621cae6c805dbd45)
1 /* $OpenBSD: pftop.c,v 1.34 2016/04/13 05:25:45 jasper Exp $	 */
2 /*
3  * Copyright (c) 2001, 2007 Can Erkin Acar
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/ioctl.h>
35 #include <sys/socket.h>
36 
37 #include <net/if.h>
38 #include <netinet/in.h>
39 #include <netinet/tcp.h>
40 #include <netinet/tcp_fsm.h>
41 #include <net/pfvar.h>
42 #include <arpa/inet.h>
43 
44 #include <net/hfsc.h>
45 
46 #include <ctype.h>
47 #include <curses.h>
48 #include <err.h>
49 #include <errno.h>
50 #include <fcntl.h>
51 #include <netdb.h>
52 #include <signal.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57 #include <limits.h>
58 #include <stdarg.h>
59 
60 #include "systat.h"
61 #include "engine.h"
62 #include "cache.h"
63 
64 extern const char *tcpstates[];
65 
66 #define MIN_NUM_STATES 1024
67 #define NUM_STATE_INC  1024
68 
69 #define DEFAULT_CACHE_SIZE 10000
70 
71 /* XXX must also check type before use */
72 #define PT_ADDR(x) (&(x)->addr.v.a.addr)
73 
74 /* XXX must also check type before use */
75 #define PT_MASK(x) (&(x)->addr.v.a.mask)
76 
77 #define PT_NOROUTE(x) ((x)->addr.type == PF_ADDR_NOROUTE)
78 
79 /* view management */
80 int select_states(void);
81 int read_states(void);
82 void sort_states(void);
83 void print_states(void);
84 
85 int select_rules(void);
86 int read_rules(void);
87 void print_rules(void);
88 
89 int select_queues(void);
90 int read_queues(void);
91 void print_queues(void);
92 
93 void update_cache(void);
94 
95 /* qsort callbacks */
96 int sort_size_callback(const void *s1, const void *s2);
97 int sort_exp_callback(const void *s1, const void *s2);
98 int sort_pkt_callback(const void *s1, const void *s2);
99 int sort_age_callback(const void *s1, const void *s2);
100 int sort_sa_callback(const void *s1, const void *s2);
101 int sort_sp_callback(const void *s1, const void *s2);
102 int sort_da_callback(const void *s1, const void *s2);
103 int sort_dp_callback(const void *s1, const void *s2);
104 int sort_rate_callback(const void *s1, const void *s2);
105 int sort_peak_callback(const void *s1, const void *s2);
106 int pf_dev = -1;
107 
108 struct sc_ent **state_cache = NULL;
109 struct pfsync_state *state_buf = NULL;
110 int state_buf_len = 0;
111 u_int32_t *state_ord = NULL;
112 u_int32_t num_states = 0;
113 u_int32_t num_states_all = 0;
114 u_int32_t num_rules = 0;
115 u_int32_t num_queues = 0;
116 int cachestates = 0;
117 
118 char *filter_string = NULL;
119 
120 #define MIN_LABEL_SIZE 5
121 #define ANCHOR_FLD_SIZE 12
122 
123 /* Define fields */
124 field_def fields[] = {
125 	{"SRC", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
126 	{"DEST", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
127 	{"GW", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
128 	{"STATE", 5, 23, 18, FLD_ALIGN_COLUMN, -1, 0, 0, 0},
129 	{"AGE", 5, 9, 4, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
130 	{"EXP", 5, 9, 4, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
131 	{"PR ", 4, 9, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
132 	{"DIR", 1, 3, 2, FLD_ALIGN_CENTER, -1, 0, 0, 0},
133 	{"PKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
134 	{"BYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
135 	{"RULE", 2, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
136 	{"LABEL", MIN_LABEL_SIZE, MIN_LABEL_SIZE, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
137 	{"STATES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
138 	{"EVAL", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
139 	{"ACTION", 1, 8, 4, FLD_ALIGN_LEFT, -1, 0, 0, 0},
140 	{"LOG", 1, 3, 2, FLD_ALIGN_LEFT, -1, 0, 0, 0},
141 	{"QUICK", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
142 	{"KS", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
143 	{"IF", 4, 6, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
144 	{"INFO", 40, 80, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
145 	{"MAX", 3, 5, 2, FLD_ALIGN_RIGHT, -1, 0, 0},
146 	{"RATE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
147 	{"AVG", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
148 	{"PEAK", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
149 	{"ANCHOR", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0},
150 	{"QUEUE", 15, 30, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
151 	{"BW", 4, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
152 	{"SCH", 3, 4, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
153 	{"PRIO", 1, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
154 	{"DROP_P", 6, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
155 	{"DROP_B", 6, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
156 	{"QLEN", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
157 	{"BORROW", 4, 6, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
158 	{"SUSPENDS", 4, 6, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
159 	{"P/S", 3, 7, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
160 	{"B/S", 4, 7, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}
161 };
162 
163 
164 /* for states */
165 #define FLD_SRC     FIELD_ADDR(fields,0)
166 #define FLD_DEST    FIELD_ADDR(fields,1)
167 #define FLD_GW      FIELD_ADDR(fields,2)
168 #define FLD_STATE   FIELD_ADDR(fields,3)
169 #define FLD_AGE     FIELD_ADDR(fields,4)
170 #define FLD_EXP     FIELD_ADDR(fields,5)
171 /* common */
172 #define FLD_PROTO   FIELD_ADDR(fields,6)
173 #define FLD_DIR     FIELD_ADDR(fields,7)
174 #define FLD_PKTS    FIELD_ADDR(fields,8)
175 #define FLD_BYTES   FIELD_ADDR(fields,9)
176 #define FLD_RULE    FIELD_ADDR(fields,10)
177 /* for rules */
178 #define FLD_LABEL   FIELD_ADDR(fields,11)
179 #define FLD_STATS   FIELD_ADDR(fields,12)
180 #define FLD_EVAL    FIELD_ADDR(fields,13)
181 #define FLD_ACTION  FIELD_ADDR(fields,14)
182 #define FLD_LOG     FIELD_ADDR(fields,15)
183 #define FLD_QUICK   FIELD_ADDR(fields,16)
184 #define FLD_KST     FIELD_ADDR(fields,17)
185 #define FLD_IF      FIELD_ADDR(fields,18)
186 #define FLD_RINFO   FIELD_ADDR(fields,19)
187 #define FLD_STMAX   FIELD_ADDR(fields,20)
188 /* other */
189 #define FLD_SI      FIELD_ADDR(fields,21)    /* instantaneous speed */
190 #define FLD_SA      FIELD_ADDR(fields,22)    /* average speed */
191 #define FLD_SP      FIELD_ADDR(fields,23)    /* peak speed */
192 #define FLD_ANCHOR  FIELD_ADDR(fields,24)
193 /* for queues */
194 #define FLD_QUEUE   FIELD_ADDR(fields,25)
195 #define FLD_BANDW   FIELD_ADDR(fields,26)
196 #define FLD_SCHED   FIELD_ADDR(fields,27)
197 #define FLD_PRIO    FIELD_ADDR(fields,28)
198 #define FLD_DROPP   FIELD_ADDR(fields,29)
199 #define FLD_DROPB   FIELD_ADDR(fields,30)
200 #define FLD_QLEN    FIELD_ADDR(fields,31)
201 #define FLD_BORR    FIELD_ADDR(fields,32)
202 #define FLD_SUSP    FIELD_ADDR(fields,33)
203 #define FLD_PKTSPS  FIELD_ADDR(fields,34)
204 #define FLD_BYTESPS FIELD_ADDR(fields,35)
205 
206 /* Define views */
207 field_def *view0[] = {
208 	FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_STATE,
209 	FLD_AGE, FLD_EXP, FLD_PKTS, FLD_BYTES, NULL
210 };
211 
212 field_def *view1[] = {
213 	FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_GW, FLD_STATE, FLD_AGE,
214 	FLD_EXP, FLD_PKTS, FLD_BYTES, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, NULL
215 };
216 
217 field_def *view2[] = {
218 	FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_STATE, FLD_AGE, FLD_EXP,
219 	FLD_PKTS, FLD_BYTES, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
220 };
221 
222 field_def *view3[] = {
223 	FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_AGE, FLD_EXP, FLD_PKTS,
224 	FLD_BYTES, FLD_STATE, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
225 };
226 
227 field_def *view4[] = {
228 	FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_PKTS, FLD_BYTES, FLD_STATE,
229 	FLD_AGE, FLD_EXP, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
230 };
231 
232 field_def *view5[] = {
233 	FLD_RULE, FLD_ANCHOR, FLD_ACTION, FLD_DIR, FLD_LOG, FLD_QUICK, FLD_IF,
234 	FLD_PROTO, FLD_KST, FLD_PKTS, FLD_BYTES, FLD_STATS, FLD_STMAX,
235 	FLD_RINFO, NULL
236 };
237 
238 field_def *view6[] = {
239 	FLD_RULE, FLD_LABEL, FLD_PKTS, FLD_BYTES, FLD_STATS, FLD_STMAX,
240 	FLD_ACTION, FLD_DIR, FLD_LOG, FLD_QUICK, FLD_IF, FLD_PROTO,
241 	FLD_ANCHOR, FLD_KST, NULL
242 };
243 
244 field_def *view7[] = {
245 	FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST,  FLD_SI, FLD_SP, FLD_SA,
246 	FLD_BYTES, FLD_STATE, FLD_PKTS, FLD_AGE, FLD_EXP, FLD_RULE, FLD_GW, NULL
247 };
248 
249 field_def *view8[] = {
250 	FLD_QUEUE, FLD_BANDW, FLD_SCHED, FLD_PRIO, FLD_PKTS, FLD_BYTES,
251 	FLD_DROPP, FLD_DROPB, FLD_QLEN, FLD_BORR, FLD_SUSP, FLD_PKTSPS,
252 	FLD_BYTESPS, NULL
253 };
254 
255 /* Define orderings */
256 order_type order_list[] = {
257 	{"none", "none", 'N', NULL},
258 	{"bytes", "bytes", 'B', sort_size_callback},
259 	{"expiry", "exp", 'E', sort_exp_callback},
260 	{"packets", "pkt", 'P', sort_pkt_callback},
261 	{"age", "age", 'A', sort_age_callback},
262 	{"source addr", "src", 'F', sort_sa_callback},
263 	{"dest. addr", "dest", 'T', sort_da_callback},
264 	{"source port", "sport", 'S', sort_sp_callback},
265 	{"dest. port", "dport", 'D', sort_dp_callback},
266 	{"rate", "rate", 'R', sort_rate_callback},
267 	{"peak", "peak", 'K', sort_peak_callback},
268 	{NULL, NULL, 0, NULL}
269 };
270 
271 /* Define view managers */
272 struct view_manager state_mgr = {
273 	"States", select_states, read_states, sort_states, print_header,
274 	print_states, keyboard_callback, order_list, NULL
275 };
276 
277 struct view_manager rule_mgr = {
278 	"Rules", select_rules, read_rules, NULL, print_header,
279 	print_rules, keyboard_callback, NULL, NULL
280 };
281 
282 struct view_manager queue_mgr = {
283 	"Queues", select_queues, read_queues, NULL, print_header,
284 	print_queues, keyboard_callback, NULL, NULL
285 };
286 
287 field_view views[] = {
288 	{view2, "states", '8', &state_mgr},
289 	{view5, "rules", '9', &rule_mgr},
290 	{view8, "queues", 'Q', &queue_mgr},
291 	{NULL, NULL, 0, NULL}
292 };
293 
294 /* queue structures from pfctl */
295 
296 struct queue_stats {
297 	struct hfsc_class_stats	 data;
298 	int			 valid;
299 	struct timeval		 timestamp;
300 };
301 
302 struct pfctl_queue_node {
303 	TAILQ_ENTRY(pfctl_queue_node)	entries;
304 	struct pf_queuespec		qs;
305 	struct queue_stats		qstats;
306 	struct queue_stats		qstats_last;
307 	int				depth;
308 };
309 TAILQ_HEAD(qnodes, pfctl_queue_node) qnodes = TAILQ_HEAD_INITIALIZER(qnodes);
310 
311 /* ordering functions */
312 
313 int
314 sort_size_callback(const void *s1, const void *s2)
315 {
316 	u_int64_t b1 = COUNTER(state_buf[* (u_int32_t *) s1].bytes[0]) +
317 		COUNTER(state_buf[* (u_int32_t *) s1].bytes[1]);
318 	u_int64_t b2 = COUNTER(state_buf[* (u_int32_t *) s2].bytes[0]) +
319 		COUNTER(state_buf[* (u_int32_t *) s2].bytes[1]);
320 	if (b2 > b1)
321 		return sortdir;
322 	if (b2 < b1)
323 		return -sortdir;
324 	return 0;
325 }
326 
327 int
328 sort_pkt_callback(const void *s1, const void *s2)
329 {
330 	u_int64_t p1 = COUNTER(state_buf[* (u_int32_t *) s1].packets[0]) +
331 		COUNTER(state_buf[* (u_int32_t *) s1].packets[1]);
332 	u_int64_t p2 = COUNTER(state_buf[* (u_int32_t *) s2].packets[0]) +
333 		COUNTER(state_buf[* (u_int32_t *) s2].packets[1]);
334 	if (p2 > p1)
335 		return sortdir;
336 	if (p2 < p1)
337 		return -sortdir;
338 	return 0;
339 }
340 
341 int
342 sort_age_callback(const void *s1, const void *s2)
343 {
344 	if (ntohl(state_buf[* (u_int32_t *) s2].creation) >
345 	    ntohl(state_buf[* (u_int32_t *) s1].creation))
346 		return sortdir;
347 	if (ntohl(state_buf[* (u_int32_t *) s2].creation) <
348 	    ntohl(state_buf[* (u_int32_t *) s1].creation))
349 		return -sortdir;
350 	return 0;
351 }
352 
353 int
354 sort_exp_callback(const void *s1, const void *s2)
355 {
356 	if (ntohl(state_buf[* (u_int32_t *) s2].expire) >
357 	    ntohl(state_buf[* (u_int32_t *) s1].expire))
358 		return sortdir;
359 	if (ntohl(state_buf[* (u_int32_t *) s2].expire) <
360 	    ntohl(state_buf[* (u_int32_t *) s1].expire))
361 		return -sortdir;
362 	return 0;
363 }
364 
365 int
366 sort_rate_callback(const void *s1, const void *s2)
367 {
368 	struct sc_ent *e1 = state_cache[* (u_int32_t *) s1];
369 	struct sc_ent *e2 = state_cache[* (u_int32_t *) s2];
370 
371 	if (e1 == NULL)
372 		return sortdir;
373 	if (e2 == NULL)
374 		return -sortdir;
375 
376 	if (e2->rate > e1 -> rate)
377 		return sortdir;
378 	if (e2->rate < e1 -> rate)
379 		return -sortdir;
380 	return 0;
381 }
382 
383 int
384 sort_peak_callback(const void *s1, const void *s2)
385 {
386 	struct sc_ent *e1 = state_cache[* (u_int32_t *) s1];
387 	struct sc_ent *e2 = state_cache[* (u_int32_t *) s2];
388 
389 	if (e2 == NULL)
390 		return -sortdir;
391 	if (e1 == NULL || e2 == NULL)
392 		return 0;
393 
394 	if (e2->peak > e1 -> peak)
395 		return sortdir;
396 	if (e2->peak < e1 -> peak)
397 		return -sortdir;
398 	return 0;
399 }
400 
401 int
402 compare_addr(int af, const struct pf_addr *a, const struct pf_addr *b)
403 {
404 	switch (af) {
405 	case AF_INET:
406 		if (ntohl(a->addr32[0]) > ntohl(b->addr32[0]))
407 			return 1;
408 		if (a->addr32[0] != b->addr32[0])
409 			return -1;
410 		break;
411 	case AF_INET6:
412 		if (ntohl(a->addr32[0]) > ntohl(b->addr32[0]))
413 			return 1;
414 		if (a->addr32[0] != b->addr32[0])
415 			return -1;
416 		if (ntohl(a->addr32[1]) > ntohl(b->addr32[1]))
417 			return 1;
418 		if (a->addr32[1] != b->addr32[1])
419 			return -1;
420 		if (ntohl(a->addr32[2]) > ntohl(b->addr32[2]))
421 			return 1;
422 		if (a->addr32[2] != b->addr32[2])
423 			return -1;
424 		if (ntohl(a->addr32[3]) > ntohl(b->addr32[3]))
425 			return 1;
426 		if (a->addr32[3] != b->addr32[3])
427 			return -1;
428 		break;
429 	}
430 
431 	return 0;
432 }
433 
434 static __inline int
435 sort_addr_callback(const struct pfsync_state *s1,
436 		   const struct pfsync_state *s2, int dir)
437 {
438 	const struct pf_addr *aa, *ab;
439 	u_int16_t pa, pb;
440 	int af, side, ret, ii, io;
441 
442 	side = s1->direction == PF_IN ? PF_SK_STACK : PF_SK_WIRE;
443 
444 	if (s1->key[side].af > s2->key[side].af)
445 		return sortdir;
446 	if (s1->key[side].af < s2->key[side].af)
447 		return -sortdir;
448 
449 	ii = io = 0;
450 
451 	if (dir == PF_OUT)	/* looking for source addr */
452 		io = 1;
453 	else			/* looking for dest addr */
454 		ii = 1;
455 
456 	if (s1->key[PF_SK_STACK].af != s1->key[PF_SK_WIRE].af) {
457 		dir = PF_OUT;
458 		side = PF_SK_STACK;
459 	} else {
460 		dir = s1->direction;
461 		side = PF_SK_WIRE;
462 	}
463 
464 	if (dir == PF_IN) {
465 		aa = &s1->key[PF_SK_STACK].addr[ii];
466 		pa =  s1->key[PF_SK_STACK].port[ii];
467 		af = s1->key[PF_SK_STACK].af;
468 	} else {
469 		aa = &s1->key[side].addr[io];
470 		pa =  s1->key[side].port[io];
471 		af = s1->key[side].af;
472 	}
473 
474 	if (s2->key[PF_SK_STACK].af != s2->key[PF_SK_WIRE].af) {
475 		dir = PF_OUT;
476 		side = PF_SK_STACK;
477 	} else {
478 		dir = s2->direction;
479 		side = PF_SK_WIRE;
480 	}
481 
482 	if (dir == PF_IN) {
483 		ab = &s2->key[PF_SK_STACK].addr[ii];
484 		pb =  s2->key[PF_SK_STACK].port[ii];
485 		af = s1->key[PF_SK_STACK].af;
486 	} else {
487 		ab = &s2->key[side].addr[io];
488 		pb =  s2->key[side].port[io];
489 		af = s1->key[side].af;
490 	}
491 
492 	ret = compare_addr(af, aa, ab);
493 	if (ret)
494 		return ret * sortdir;
495 
496 	if (ntohs(pa) > ntohs(pb))
497 		return sortdir;
498 	return -sortdir;
499 }
500 
501 static __inline int
502 sort_port_callback(const struct pfsync_state *s1,
503 		   const struct pfsync_state *s2, int dir)
504 {
505 	const struct pf_addr *aa, *ab;
506 	u_int16_t pa, pb;
507 	int af, side, ret, ii, io;
508 
509 	side = s1->direction == PF_IN ? PF_SK_STACK : PF_SK_WIRE;
510 
511 	if (s1->key[side].af > s2->key[side].af)
512 		return sortdir;
513 	if (s1->key[side].af < s2->key[side].af)
514 		return -sortdir;
515 
516 	ii = io = 0;
517 
518 	if (dir == PF_OUT)	/* looking for source addr */
519 		io = 1;
520 	else			/* looking for dest addr */
521 		ii = 1;
522 
523 	if (s1->key[PF_SK_STACK].af != s1->key[PF_SK_WIRE].af) {
524 		dir = PF_OUT;
525 		side = PF_SK_STACK;
526 	} else {
527 		dir = s1->direction;
528 		side = PF_SK_WIRE;
529 	}
530 
531 	if (dir == PF_IN) {
532 		aa = &s1->key[PF_SK_STACK].addr[ii];
533 		pa =  s1->key[PF_SK_STACK].port[ii];
534 		af = s1->key[PF_SK_STACK].af;
535 	} else {
536 		aa = &s1->key[side].addr[io];
537 		pa =  s1->key[side].port[io];
538 		af = s1->key[side].af;
539 	}
540 
541 	if (s2->key[PF_SK_STACK].af != s2->key[PF_SK_WIRE].af) {
542 		dir = PF_OUT;
543 		side = PF_SK_STACK;
544 	} else {
545 		dir = s2->direction;
546 		side = PF_SK_WIRE;
547 	}
548 
549 	if (dir == PF_IN) {
550 		ab = &s2->key[PF_SK_STACK].addr[ii];
551 		pb =  s2->key[PF_SK_STACK].port[ii];
552 		af = s1->key[PF_SK_STACK].af;
553 	} else {
554 		ab = &s2->key[side].addr[io];
555 		pb =  s2->key[side].port[io];
556 		af = s1->key[side].af;
557 	}
558 
559 
560 	if (ntohs(pa) > ntohs(pb))
561 		return sortdir;
562 	if (ntohs(pa) < ntohs(pb))
563 		return - sortdir;
564 
565 	ret = compare_addr(af, aa, ab);
566 	if (ret)
567 		return ret * sortdir;
568 	return -sortdir;
569 }
570 
571 int
572 sort_sa_callback(const void *p1, const void *p2)
573 {
574 	struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1);
575 	struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2);
576 	return sort_addr_callback(s1, s2, PF_OUT);
577 }
578 
579 int
580 sort_da_callback(const void *p1, const void *p2)
581 {
582 	struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1);
583 	struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2);
584 	return sort_addr_callback(s1, s2, PF_IN);
585 }
586 
587 int
588 sort_sp_callback(const void *p1, const void *p2)
589 {
590 	struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1);
591 	struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2);
592 	return sort_port_callback(s1, s2, PF_OUT);
593 }
594 
595 int
596 sort_dp_callback(const void *p1, const void *p2)
597 {
598 	struct pfsync_state *s1 = state_buf + (* (u_int32_t *) p1);
599 	struct pfsync_state *s2 = state_buf + (* (u_int32_t *) p2);
600 	return sort_port_callback(s1, s2, PF_IN);
601 }
602 
603 void
604 sort_states(void)
605 {
606 	order_type *ordering;
607 
608 	if (curr_mgr == NULL)
609 		return;
610 
611 	ordering = curr_mgr->order_curr;
612 
613 	if (ordering == NULL)
614 		return;
615 	if (ordering->func == NULL)
616 		return;
617 	if (state_buf == NULL)
618 		return;
619 	if (num_states <= 0)
620 		return;
621 
622 	mergesort(state_ord, num_states, sizeof(u_int32_t), ordering->func);
623 }
624 
625 /* state management functions */
626 
627 void
628 alloc_buf(int ns)
629 {
630 	int len;
631 
632 	if (ns < MIN_NUM_STATES)
633 		ns = MIN_NUM_STATES;
634 
635 	len = ns;
636 
637 	if (len >= state_buf_len) {
638 		len += NUM_STATE_INC;
639 		state_buf = reallocarray(state_buf, len,
640 		    sizeof(struct pfsync_state));
641 		state_ord = reallocarray(state_ord, len, sizeof(u_int32_t));
642 		state_cache = reallocarray(state_cache, len,
643 		    sizeof(struct sc_ent *));
644 		if (state_buf == NULL || state_ord == NULL ||
645 		    state_cache == NULL)
646 			err(1, "realloc");
647 		state_buf_len = len;
648 	}
649 }
650 
651 int
652 select_states(void)
653 {
654 	num_disp = num_states;
655 	return (0);
656 }
657 
658 int
659 read_states(void)
660 {
661 	struct pfioc_states ps;
662 	int n;
663 
664 	if (pf_dev == -1)
665 		return -1;
666 
667 	for (;;) {
668 		int sbytes = state_buf_len * sizeof(struct pfsync_state);
669 
670 		ps.ps_len = sbytes;
671 		ps.ps_buf = (char *) state_buf;
672 
673 		if (ioctl(pf_dev, DIOCGETSTATES, &ps) < 0) {
674 			error("DIOCGETSTATES");
675 		}
676 		num_states_all = ps.ps_len / sizeof(struct pfsync_state);
677 
678 		if (ps.ps_len < sbytes)
679 			break;
680 
681 		alloc_buf(num_states_all);
682 	}
683 
684 	num_states =  num_states_all;
685 	for (n = 0; n<num_states_all; n++)
686 		state_ord[n] = n;
687 
688 	if (cachestates) {
689 		for (n = 0; n < num_states; n++)
690 			state_cache[n] = cache_state(state_buf + n);
691 		cache_endupdate();
692 	}
693 
694 	num_disp = num_states;
695 	return 0;
696 }
697 
698 int
699 unmask(struct pf_addr * m, u_int8_t af)
700 {
701 	int i = 31, j = 0, b = 0, msize;
702 	u_int32_t tmp;
703 
704 	if (af == AF_INET)
705 		msize = 1;
706 	else
707 		msize = 4;
708 	while (j < msize && m->addr32[j] == 0xffffffff) {
709 		b += 32;
710 		j++;
711 	}
712 	if (j < msize) {
713 		tmp = ntohl(m->addr32[j]);
714 		for (i = 31; tmp & (1 << i); --i)
715 			b++;
716 	}
717 	return (b);
718 }
719 
720 /* display functions */
721 
722 void
723 tb_print_addr(struct pf_addr * addr, struct pf_addr * mask, int af)
724 {
725 		switch (af) {
726 		case AF_INET: {
727 			tbprintf("%s", inetname(addr->v4));
728 			break;
729 		}
730 		case AF_INET6: {
731 			tbprintf("%s", inet6name(&addr->v6));
732 			break;
733 		}
734 	}
735 
736 	if (mask != NULL) {
737 		if (!PF_AZERO(mask, af))
738 			tbprintf("/%u", unmask(mask, af));
739 	}
740 }
741 
742 void
743 print_fld_host2(field_def *fld, struct pfsync_state_key *ks,
744 		struct pfsync_state_key *kn, int idx)
745 {
746 	struct pf_addr *as = &ks->addr[idx];
747 	struct pf_addr *an = &kn->addr[idx];
748 
749 	u_int16_t ps = ntohs(ks->port[idx]);
750 	u_int16_t pn = ntohs(kn->port[idx]);
751 
752 	int asf = ks->af;
753 	int anf = kn->af;
754 
755 	if (fld == NULL)
756 		return;
757 
758 	if (fld->width < 3) {
759 		print_fld_str(fld, "*");
760 		return;
761 	}
762 
763 	tb_start();
764 	tb_print_addr(as, NULL, asf);
765 
766 	if (asf == AF_INET)
767 		tbprintf(":%u", ps);
768 	else
769 		tbprintf("[%u]", ps);
770 
771 	print_fld_tb(fld);
772 
773 	if (asf != anf || PF_ANEQ(as, an, asf) || ps != pn) {
774 		tb_start();
775 		tb_print_addr(an, NULL, anf);
776 
777 		if (anf == AF_INET)
778 			tbprintf(":%u", pn);
779 		else
780 			tbprintf("[%u]", pn);
781 		print_fld_tb(FLD_GW);
782 	}
783 
784 }
785 
786 void
787 print_fld_state(field_def *fld, unsigned int proto,
788 		unsigned int s1, unsigned int s2)
789 {
790 	int len;
791 
792 	if (fld == NULL)
793 		return;
794 
795 	len = fld->width;
796 	if (len < 1)
797 		return;
798 
799 	tb_start();
800 
801 	if (proto == IPPROTO_TCP) {
802 		if (s1 <= TCPS_TIME_WAIT && s2 <= TCPS_TIME_WAIT)
803 			tbprintf("%s:%s", tcpstates[s1], tcpstates[s2]);
804 #ifdef PF_TCPS_PROXY_SRC
805 		else if (s1 == PF_TCPS_PROXY_SRC ||
806 			   s2 == PF_TCPS_PROXY_SRC)
807 			tbprintf("PROXY:SRC\n");
808 		else if (s1 == PF_TCPS_PROXY_DST ||
809 			 s2 == PF_TCPS_PROXY_DST)
810 			tbprintf("PROXY:DST\n");
811 #endif
812 		else
813 			tbprintf("<BAD STATE LEVELS>");
814 	} else if (proto == IPPROTO_UDP && s1 < PFUDPS_NSTATES &&
815 		   s2 < PFUDPS_NSTATES) {
816 		const char *states[] = PFUDPS_NAMES;
817 		tbprintf("%s:%s", states[s1], states[s2]);
818 	} else if (proto != IPPROTO_ICMP && s1 < PFOTHERS_NSTATES &&
819 		   s2 < PFOTHERS_NSTATES) {
820 		/* XXX ICMP doesn't really have state levels */
821 		const char *states[] = PFOTHERS_NAMES;
822 		tbprintf("%s:%s", states[s1], states[s2]);
823 	} else {
824 		tbprintf("%u:%u", s1, s2);
825 	}
826 
827 	if (strlen(tmp_buf) > len) {
828 		tb_start();
829 		tbprintf("%u:%u", s1, s2);
830 	}
831 
832 	print_fld_tb(fld);
833 }
834 
835 int
836 print_state(struct pfsync_state * s, struct sc_ent * ent)
837 {
838 	struct pfsync_state_peer *src, *dst;
839 	struct protoent *p;
840 	u_int64_t sz;
841 	int afto, dir;
842 
843 	afto = s->key[PF_SK_STACK].af == s->key[PF_SK_WIRE].af ? 0 : 1;
844 	dir = afto ? PF_OUT : s->direction;
845 
846 	if (dir == PF_OUT) {
847 		src = &s->src;
848 		dst = &s->dst;
849 	} else {
850 		src = &s->dst;
851 		dst = &s->src;
852 	}
853 
854 	p = getprotobynumber(s->proto);
855 
856 	if (p != NULL)
857 		print_fld_str(FLD_PROTO, p->p_name);
858 	else
859 		print_fld_uint(FLD_PROTO, s->proto);
860 
861 	if (dir == PF_OUT) {
862 		print_fld_host2(FLD_SRC,
863 		    &s->key[afto ? PF_SK_STACK : PF_SK_WIRE],
864 		    &s->key[PF_SK_STACK], 1);
865 		print_fld_host2(FLD_DEST,
866 		    &s->key[afto ? PF_SK_STACK : PF_SK_WIRE],
867 		    &s->key[afto ? PF_SK_WIRE : PF_SK_STACK], 0);
868 	} else {
869 		print_fld_host2(FLD_SRC, &s->key[PF_SK_STACK],
870 		    &s->key[PF_SK_WIRE], 0);
871 		print_fld_host2(FLD_DEST, &s->key[PF_SK_STACK],
872 		    &s->key[PF_SK_WIRE], 1);
873 	}
874 
875 	if (dir == PF_OUT)
876 		print_fld_str(FLD_DIR, "Out");
877 	else
878 		print_fld_str(FLD_DIR, "In");
879 
880 	print_fld_state(FLD_STATE, s->proto, src->state, dst->state);
881 	print_fld_age(FLD_AGE, ntohl(s->creation));
882 	print_fld_age(FLD_EXP, ntohl(s->expire));
883 
884 	sz = COUNTER(s->bytes[0]) + COUNTER(s->bytes[1]);
885 
886 	print_fld_size(FLD_PKTS, COUNTER(s->packets[0]) +
887 		       COUNTER(s->packets[1]));
888 	print_fld_size(FLD_BYTES, sz);
889 	print_fld_rate(FLD_SA, (s->creation) ?
890 		       ((double)sz/(double)ntohl(s->creation)) : -1);
891 
892 	print_fld_uint(FLD_RULE, ntohl(s->rule));
893 	if (cachestates && ent != NULL) {
894 		print_fld_rate(FLD_SI, ent->rate);
895 		print_fld_rate(FLD_SP, ent->peak);
896 	}
897 
898 	end_line();
899 	return 1;
900 }
901 
902 void
903 print_states(void)
904 {
905 	int n, count = 0;
906 
907 	for (n = dispstart; n < num_disp; n++) {
908 		count += print_state(state_buf + state_ord[n],
909 				     state_cache[state_ord[n]]);
910 		if (maxprint > 0 && count >= maxprint)
911 			break;
912 	}
913 }
914 
915 /* rule display */
916 
917 struct pf_rule *rules = NULL;
918 u_int32_t alloc_rules = 0;
919 
920 int
921 select_rules(void)
922 {
923 	num_disp = num_rules;
924 	return (0);
925 }
926 
927 
928 void
929 add_rule_alloc(u_int32_t nr)
930 {
931 	if (nr == 0)
932 		return;
933 
934 	num_rules += nr;
935 
936 	if (rules == NULL) {
937 		rules = reallocarray(NULL, num_rules, sizeof(struct pf_rule));
938 		if (rules == NULL)
939 			err(1, "malloc");
940 		alloc_rules = num_rules;
941 	} else if (num_rules > alloc_rules) {
942 		rules = reallocarray(rules, num_rules, sizeof(struct pf_rule));
943 		if (rules == NULL)
944 			err(1, "realloc");
945 		alloc_rules = num_rules;
946 	}
947 }
948 
949 int label_length;
950 
951 int
952 read_anchor_rules(char *anchor)
953 {
954 	struct pfioc_rule pr;
955 	u_int32_t nr, num, off;
956 	int len;
957 
958 	if (pf_dev < 0)
959 		return (-1);
960 
961 	memset(&pr, 0, sizeof(pr));
962 	strlcpy(pr.anchor, anchor, sizeof(pr.anchor));
963 
964 	if (ioctl(pf_dev, DIOCGETRULES, &pr)) {
965 		error("anchor %s: %s", anchor, strerror(errno));
966 		return (-1);
967 	}
968 
969 	off = num_rules;
970 	num = pr.nr;
971 	add_rule_alloc(num);
972 
973 	for (nr = 0; nr < num; ++nr) {
974 		pr.nr = nr;
975 		if (ioctl(pf_dev, DIOCGETRULE, &pr)) {
976 			error("DIOCGETRULE: %s", strerror(errno));
977 			return (-1);
978 		}
979 		/* XXX overload pr.anchor, to store a pointer to
980 		 * anchor name */
981 		pr.rule.anchor = (struct pf_anchor *) anchor;
982 		len = strlen(pr.rule.label);
983 		if (len > label_length)
984 			label_length = len;
985 		rules[off + nr] = pr.rule;
986 	}
987 
988 	return (num);
989 }
990 
991 struct anchor_name {
992 	char name[PATH_MAX];
993 	struct anchor_name *next;
994 	u_int32_t ref;
995 };
996 
997 struct anchor_name *anchor_root = NULL;
998 struct anchor_name *anchor_end = NULL;
999 struct anchor_name *anchor_free = NULL;
1000 
1001 struct anchor_name*
1002 alloc_anchor_name(const char *path)
1003 {
1004 	struct anchor_name *a;
1005 
1006 	a = anchor_free;
1007 	if (a == NULL) {
1008 		a = malloc(sizeof(struct anchor_name));
1009 		if (a == NULL)
1010 			return (NULL);
1011 	} else
1012 		anchor_free = a->next;
1013 
1014 	if (anchor_root == NULL)
1015 		anchor_end = a;
1016 
1017 	a->next = anchor_root;
1018 	anchor_root = a;
1019 
1020 	a->ref = 0;
1021 	strlcpy(a->name, path, sizeof(a->name));
1022 	return (a);
1023 }
1024 
1025 void
1026 reset_anchor_names(void)
1027 {
1028 	if (anchor_end == NULL)
1029 		return;
1030 
1031 	anchor_end->next = anchor_free;
1032 	anchor_free = anchor_root;
1033 	anchor_root = anchor_end = NULL;
1034 }
1035 
1036 struct pfioc_ruleset ruleset;
1037 char *rs_end = NULL;
1038 
1039 int
1040 read_rulesets(const char *path)
1041 {
1042 	char *pre;
1043 	struct anchor_name *a;
1044 	u_int32_t nr, ns;
1045 	int len;
1046 
1047 	if (path == NULL)
1048 		ruleset.path[0] = '\0';
1049 	else if (strlcpy(ruleset.path, path, sizeof(ruleset.path)) >=
1050 	    sizeof(ruleset.path))
1051 		 return (-1);
1052 
1053 	/* a persistent storage for anchor names */
1054 	a = alloc_anchor_name(ruleset.path);
1055 	if (a == NULL)
1056 		return (-1);
1057 
1058 	len = read_anchor_rules(a->name);
1059 	if (len < 0)
1060 		return (-1);
1061 
1062 	a->ref += len;
1063 
1064 	if (ioctl(pf_dev, DIOCGETRULESETS, &ruleset)) {
1065 		error("DIOCGETRULESETS: %s", strerror(errno));
1066 		return (-1);
1067 	}
1068 
1069 	ns = ruleset.nr;
1070 
1071 	if (rs_end == NULL)
1072 		rs_end = ruleset.path + sizeof(ruleset.path);
1073 
1074 	/* 'pre' tracks the previous level on the anchor */
1075 	pre = strchr(ruleset.path, 0);
1076 	len = rs_end - pre;
1077 	if (len < 1)
1078 		return (-1);
1079 	--len;
1080 
1081 	for (nr = 0; nr < ns; ++nr) {
1082 		ruleset.nr = nr;
1083 		if (ioctl(pf_dev, DIOCGETRULESET, &ruleset)) {
1084 			error("DIOCGETRULESET: %s", strerror(errno));
1085 			return (-1);
1086 		}
1087 		*pre = '/';
1088 		if (strlcpy(pre + 1, ruleset.name, len) < len)
1089 			read_rulesets(ruleset.path);
1090 		*pre = '\0';
1091 	}
1092 
1093 	return (0);
1094 }
1095 
1096 void
1097 compute_anchor_field(void)
1098 {
1099 	struct anchor_name *a;
1100 	int sum, cnt, mx, nx;
1101 	sum = cnt = mx = 0;
1102 
1103 	for (a = anchor_root; a != NULL; a = a->next, cnt++) {
1104 		int len;
1105 		if (a->ref == 0)
1106 			continue;
1107 		len = strlen(a->name);
1108 		sum += len;
1109 		if (len > mx)
1110 			mx = len;
1111 	}
1112 
1113 	nx = sum/cnt;
1114 	if (nx < ANCHOR_FLD_SIZE)
1115 		nx = (mx < ANCHOR_FLD_SIZE) ? mx : ANCHOR_FLD_SIZE;
1116 
1117 	if (FLD_ANCHOR->max_width != mx ||
1118 	    FLD_ANCHOR->norm_width != nx) {
1119 		FLD_ANCHOR->max_width = mx;
1120 		FLD_ANCHOR->norm_width = nx;
1121 		field_setup();
1122 		need_update = 1;
1123 	}
1124 }
1125 
1126 int
1127 read_rules(void)
1128 {
1129 	int ret, nw, mw;
1130 	num_rules = 0;
1131 
1132 	if (pf_dev == -1)
1133 		return (-1);
1134 
1135 	label_length = MIN_LABEL_SIZE;
1136 
1137 	reset_anchor_names();
1138 	ret = read_rulesets(NULL);
1139 	compute_anchor_field();
1140 
1141 	nw = mw = label_length;
1142 	if (nw > 16)
1143 		nw = 16;
1144 
1145 	if (FLD_LABEL->norm_width != nw ||
1146 	    FLD_LABEL->max_width != mw) {
1147 		FLD_LABEL->norm_width = nw;
1148 		FLD_LABEL->max_width = mw;
1149 		field_setup();
1150 		need_update = 1;
1151 	}
1152 
1153 	num_disp = num_rules;
1154 	return (ret);
1155 }
1156 
1157 void
1158 tb_print_addrw(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af)
1159 {
1160 	switch (addr->type) {
1161 	case PF_ADDR_ADDRMASK:
1162 		tb_print_addr(&addr->v.a.addr, mask, af);
1163 		break;
1164 	case  PF_ADDR_NOROUTE:
1165 		tbprintf("noroute");
1166 		break;
1167 	case PF_ADDR_DYNIFTL:
1168 		tbprintf("(%s)", addr->v.ifname);
1169 		break;
1170 	case PF_ADDR_TABLE:
1171 		tbprintf("<%s>", addr->v.tblname);
1172 		break;
1173 	default:
1174 		tbprintf("UNKNOWN");
1175 		break;
1176 	}
1177 }
1178 
1179 void
1180 tb_print_op(u_int8_t op, const char *a1, const char *a2)
1181 {
1182 	if (op == PF_OP_IRG)
1183 		tbprintf("%s >< %s ", a1, a2);
1184 	else if (op == PF_OP_XRG)
1185 		tbprintf("%s <> %s ", a1, a2);
1186 	else if (op == PF_OP_RRG)
1187 		tbprintf("%s:%s ", a1, a2);
1188 	else if (op == PF_OP_EQ)
1189 		tbprintf("= %s ", a1);
1190 	else if (op == PF_OP_NE)
1191 		tbprintf("!= %s ", a1);
1192 	else if (op == PF_OP_LT)
1193 		tbprintf("< %s ", a1);
1194 	else if (op == PF_OP_LE)
1195 		tbprintf("<= %s ", a1);
1196 	else if (op == PF_OP_GT)
1197 		tbprintf("> %s ", a1);
1198 	else if (op == PF_OP_GE)
1199 		tbprintf(">= %s ", a1);
1200 }
1201 
1202 void
1203 tb_print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
1204 {
1205 	char a1[6], a2[6];
1206 	struct servent *s = getservbyport(p1, proto);
1207 
1208 	p1 = ntohs(p1);
1209 	p2 = ntohs(p2);
1210 	snprintf(a1, sizeof(a1), "%u", p1);
1211 	snprintf(a2, sizeof(a2), "%u", p2);
1212 	tbprintf("port ");
1213 	if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
1214 		tb_print_op(op, s->s_name, a2);
1215 	else
1216 		tb_print_op(op, a1, a2);
1217 }
1218 
1219 void
1220 tb_print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst,
1221 		u_int8_t af, u_int8_t proto)
1222 {
1223 	if (
1224 	    PF_AZERO(PT_ADDR(src), AF_INET6) &&
1225 	    PF_AZERO(PT_ADDR(dst), AF_INET6) &&
1226 	    ! PT_NOROUTE(src) && ! PT_NOROUTE(dst) &&
1227 	    PF_AZERO(PT_MASK(src), AF_INET6) &&
1228 	    PF_AZERO(PT_MASK(dst), AF_INET6) &&
1229 	    !src->port_op && !dst->port_op)
1230 		tbprintf("all ");
1231 	else {
1232 		tbprintf("from ");
1233 		if (PT_NOROUTE(src))
1234 			tbprintf("no-route ");
1235 		else if (PF_AZERO(PT_ADDR(src), AF_INET6) &&
1236 			 PF_AZERO(PT_MASK(src), AF_INET6))
1237 			tbprintf("any ");
1238 		else {
1239 			if (src->neg)
1240 				tbprintf("! ");
1241 			tb_print_addrw(&src->addr, PT_MASK(src), af);
1242 			tbprintf(" ");
1243 		}
1244 		if (src->port_op)
1245 			tb_print_port(src->port_op, src->port[0],
1246 				      src->port[1],
1247 				      proto == IPPROTO_TCP ? "tcp" : "udp");
1248 
1249 		tbprintf("to ");
1250 		if (PT_NOROUTE(dst))
1251 			tbprintf("no-route ");
1252 		else if (PF_AZERO(PT_ADDR(dst), AF_INET6) &&
1253 			 PF_AZERO(PT_MASK(dst), AF_INET6))
1254 			tbprintf("any ");
1255 		else {
1256 			if (dst->neg)
1257 				tbprintf("! ");
1258 			tb_print_addrw(&dst->addr, PT_MASK(dst), af);
1259 			tbprintf(" ");
1260 		}
1261 		if (dst->port_op)
1262 			tb_print_port(dst->port_op, dst->port[0],
1263 				      dst->port[1],
1264 				      proto == IPPROTO_TCP ? "tcp" : "udp");
1265 	}
1266 }
1267 
1268 void
1269 tb_print_ugid(u_int8_t op, unsigned u1, unsigned u2,
1270 	      const char *t, unsigned umax)
1271 {
1272 	char	a1[11], a2[11];
1273 
1274 	snprintf(a1, sizeof(a1), "%u", u1);
1275 	snprintf(a2, sizeof(a2), "%u", u2);
1276 
1277 	tbprintf("%s ", t);
1278 	if (u1 == umax && (op == PF_OP_EQ || op == PF_OP_NE))
1279 		tb_print_op(op, "unknown", a2);
1280 	else
1281 		tb_print_op(op, a1, a2);
1282 }
1283 
1284 void
1285 tb_print_flags(u_int8_t f)
1286 {
1287 	const char *tcpflags = "FSRPAUEW";
1288 	int i;
1289 
1290 	for (i = 0; tcpflags[i]; ++i)
1291 		if (f & (1 << i))
1292 			tbprintf("%c", tcpflags[i]);
1293 }
1294 
1295 void
1296 print_rule(struct pf_rule *pr)
1297 {
1298 	static const char *actiontypes[] = { "Pass", "Block", "Scrub",
1299 	    "no Scrub", "Nat", "no Nat", "Binat", "no Binat", "Rdr",
1300 	    "no Rdr", "SynProxy Block", "Defer", "Match" };
1301 	int numact = sizeof(actiontypes) / sizeof(char *);
1302 
1303 	static const char *routetypes[] = { "", "fastroute", "route-to",
1304 	    "dup-to", "reply-to" };
1305 
1306 	int numroute = sizeof(routetypes) / sizeof(char *);
1307 
1308 	if (pr == NULL) return;
1309 
1310 	print_fld_str(FLD_LABEL, pr->label);
1311 	print_fld_size(FLD_STATS, pr->states_tot);
1312 
1313 	print_fld_size(FLD_PKTS, pr->packets[0] + pr->packets[1]);
1314 	print_fld_size(FLD_BYTES, pr->bytes[0] + pr->bytes[1]);
1315 
1316 	print_fld_uint(FLD_RULE, pr->nr);
1317 	if (pr->direction == PF_OUT)
1318 		print_fld_str(FLD_DIR, "Out");
1319 	else if (pr->direction == PF_IN)
1320 		print_fld_str(FLD_DIR, "In");
1321 	else
1322 		print_fld_str(FLD_DIR, "Any");
1323 
1324 	if (pr->quick)
1325 		print_fld_str(FLD_QUICK, "Quick");
1326 
1327 	if (pr->keep_state == PF_STATE_NORMAL)
1328 		print_fld_str(FLD_KST, "Keep");
1329 	else if (pr->keep_state == PF_STATE_MODULATE)
1330 		print_fld_str(FLD_KST, "Mod");
1331 	else if (pr->keep_state == PF_STATE_SYNPROXY)
1332 		print_fld_str(FLD_KST, "Syn");
1333 	if (pr->log == 1)
1334 		print_fld_str(FLD_LOG, "Log");
1335 	else if (pr->log == 2)
1336 		print_fld_str(FLD_LOG, "All");
1337 
1338 	if (pr->action >= numact)
1339 		print_fld_uint(FLD_ACTION, pr->action);
1340 	else print_fld_str(FLD_ACTION, actiontypes[pr->action]);
1341 
1342 	if (pr->proto) {
1343 		struct protoent *p = getprotobynumber(pr->proto);
1344 
1345 		if (p != NULL)
1346 			print_fld_str(FLD_PROTO, p->p_name);
1347 		else
1348 			print_fld_uint(FLD_PROTO, pr->proto);
1349 	}
1350 
1351 	if (pr->ifname[0]) {
1352 		tb_start();
1353 		if (pr->ifnot)
1354 			tbprintf("!");
1355 		tbprintf("%s", pr->ifname);
1356 		print_fld_tb(FLD_IF);
1357 	}
1358 	if (pr->max_states)
1359 		print_fld_uint(FLD_STMAX, pr->max_states);
1360 
1361 	/* print info field */
1362 
1363 	tb_start();
1364 
1365 	if (pr->action == PF_DROP) {
1366 		if (pr->rule_flag & PFRULE_RETURNRST)
1367 			tbprintf("return-rst ");
1368 #ifdef PFRULE_RETURN
1369 		else if (pr->rule_flag & PFRULE_RETURN)
1370 			tbprintf("return ");
1371 #endif
1372 #ifdef PFRULE_RETURNICMP
1373 		else if (pr->rule_flag & PFRULE_RETURNICMP)
1374 			tbprintf("return-icmp ");
1375 #endif
1376 		else
1377 			tbprintf("drop ");
1378 	}
1379 
1380 	if (pr->rt > 0 && pr->rt < numroute) {
1381 		tbprintf("%s ", routetypes[pr->rt]);
1382 	}
1383 
1384 	if (pr->af) {
1385 		if (pr->af == AF_INET)
1386 			tbprintf("inet ");
1387 		else
1388 			tbprintf("inet6 ");
1389 	}
1390 
1391 	tb_print_fromto(&pr->src, &pr->dst, pr->af, pr->proto);
1392 
1393 	if (pr->uid.op)
1394 		tb_print_ugid(pr->uid.op, pr->uid.uid[0], pr->uid.uid[1],
1395 		        "user", UID_MAX);
1396 	if (pr->gid.op)
1397 		tb_print_ugid(pr->gid.op, pr->gid.gid[0], pr->gid.gid[1],
1398 		        "group", GID_MAX);
1399 
1400 	if (pr->action == PF_PASS &&
1401 	    (pr->proto == 0 || pr->proto == IPPROTO_TCP) &&
1402 	    (pr->flags != TH_SYN || pr->flagset != (TH_SYN | TH_ACK) )) {
1403 		tbprintf("flags ");
1404 		if (pr->flags || pr->flagset) {
1405 			tb_print_flags(pr->flags);
1406 			tbprintf("/");
1407 			tb_print_flags(pr->flagset);
1408 		} else
1409 			tbprintf("any ");
1410 	}
1411 
1412 	tbprintf(" ");
1413 
1414 	if (pr->tos)
1415 		tbprintf("tos 0x%2.2x ", pr->tos);
1416 #ifdef PFRULE_FRAGMENT
1417 	if (pr->rule_flag & PFRULE_FRAGMENT)
1418 		tbprintf("fragment ");
1419 #endif
1420 #ifdef PFRULE_NODF
1421 	if (pr->rule_flag & PFRULE_NODF)
1422 		tbprintf("no-df ");
1423 #endif
1424 #ifdef PFRULE_RANDOMID
1425 	if (pr->rule_flag & PFRULE_RANDOMID)
1426 		tbprintf("random-id ");
1427 #endif
1428 	if (pr->min_ttl)
1429 		tbprintf("min-ttl %d ", pr->min_ttl);
1430 	if (pr->max_mss)
1431 		tbprintf("max-mss %d ", pr->max_mss);
1432 	if (pr->allow_opts)
1433 		tbprintf("allow-opts ");
1434 
1435 	/* XXX more missing */
1436 
1437 	if (pr->qname[0] && pr->pqname[0])
1438 		tbprintf("queue(%s, %s) ", pr->qname, pr->pqname);
1439 	else if (pr->qname[0])
1440 		tbprintf("queue %s ", pr->qname);
1441 
1442 	if (pr->tagname[0])
1443 		tbprintf("tag %s ", pr->tagname);
1444 	if (pr->match_tagname[0]) {
1445 		if (pr->match_tag_not)
1446 			tbprintf("! ");
1447 		tbprintf("tagged %s ", pr->match_tagname);
1448 	}
1449 
1450 	print_fld_tb(FLD_RINFO);
1451 
1452 	/* XXX anchor field overloaded with anchor name */
1453 	print_fld_str(FLD_ANCHOR, (char *)pr->anchor);
1454 	tb_end();
1455 
1456 	end_line();
1457 }
1458 
1459 void
1460 print_rules(void)
1461 {
1462 	u_int32_t n, count = 0;
1463 
1464 	for (n = dispstart; n < num_rules; n++) {
1465 		print_rule(rules + n);
1466 		count ++;
1467 		if (maxprint > 0 && count >= maxprint)
1468 			break;
1469 	}
1470 }
1471 
1472 /* queue display */
1473 struct pfctl_queue_node *
1474 pfctl_find_queue_node(const char *qname, const char *ifname)
1475 {
1476 	struct pfctl_queue_node	*node;
1477 
1478 	TAILQ_FOREACH(node, &qnodes, entries)
1479 		if (!strcmp(node->qs.qname, qname)
1480 		    && !(strcmp(node->qs.ifname, ifname)))
1481 			return (node);
1482 	return (NULL);
1483 }
1484 
1485 void
1486 pfctl_insert_queue_node(const struct pf_queuespec qs,
1487     const struct queue_stats qstats)
1488 {
1489 	struct pfctl_queue_node	*node, *parent;
1490 
1491 	node = calloc(1, sizeof(struct pfctl_queue_node));
1492 	if (node == NULL)
1493 		err(1, "pfctl_insert_queue_node: calloc");
1494 	memcpy(&node->qs, &qs, sizeof(qs));
1495 	memcpy(&node->qstats, &qstats, sizeof(qstats));
1496 
1497 	if (node->qs.parent[0]) {
1498 		parent = pfctl_find_queue_node(node->qs.parent,
1499 		    node->qs.ifname);
1500 		if (parent)
1501 			node->depth = parent->depth + 1;
1502 	}
1503 
1504 	TAILQ_INSERT_TAIL(&qnodes, node, entries);
1505 }
1506 
1507 int
1508 pfctl_update_qstats(void)
1509 {
1510 	struct pfctl_queue_node	*node;
1511 	struct pfioc_queue	 pq;
1512 	struct pfioc_qstats	 pqs;
1513 	u_int32_t		 mnr, nr;
1514 	struct queue_stats	 qstats;
1515 	static u_int32_t	 last_ticket;
1516 
1517 	memset(&pq, 0, sizeof(pq));
1518 	memset(&pqs, 0, sizeof(pqs));
1519 	memset(&qstats, 0, sizeof(qstats));
1520 
1521 	if (pf_dev < 0)
1522 		return (-1);
1523 
1524 	if (ioctl(pf_dev, DIOCGETQUEUES, &pq)) {
1525 		error("DIOCGETQUEUES: %s", strerror(errno));
1526 		return (-1);
1527 	}
1528 
1529 	/* if a new set is found, start over */
1530 	if (pq.ticket != last_ticket)
1531 		while ((node = TAILQ_FIRST(&qnodes)) != NULL) {
1532 			TAILQ_REMOVE(&qnodes, node, entries);
1533 			free(node);
1534 		}
1535 	last_ticket = pq.ticket;
1536 
1537 	num_queues = mnr = pq.nr;
1538 	for (nr = 0; nr < mnr; ++nr) {
1539 		pqs.nr = nr;
1540 		pqs.ticket = pq.ticket;
1541 		pqs.buf = &qstats.data;
1542 		pqs.nbytes = sizeof(qstats.data);
1543 		if (ioctl(pf_dev, DIOCGETQSTATS, &pqs)) {
1544 			error("DIOCGETQSTATS: %s", strerror(errno));
1545 			return (-1);
1546 		}
1547 		if (pqs.queue.qname[0] != '_') {
1548 			if (pqs.queue.parent[0] && pqs.queue.parent[0] == '_')
1549 				pqs.queue.parent[0] = '\0';
1550 			qstats.valid = 1;
1551 			gettimeofday(&qstats.timestamp, NULL);
1552 			if ((node = pfctl_find_queue_node(pqs.queue.qname,
1553 			    pqs.queue.ifname)) != NULL) {
1554 				memcpy(&node->qstats_last, &node->qstats,
1555 				    sizeof(struct queue_stats));
1556 				memcpy(&node->qstats, &qstats,
1557 				    sizeof(struct queue_stats));
1558 			} else {
1559 				pfctl_insert_queue_node(pqs.queue, qstats);
1560 			}
1561 		} else
1562 			num_queues--;
1563 	}
1564 	return (0);
1565 }
1566 
1567 int
1568 select_queues(void)
1569 {
1570 	num_disp = num_queues;
1571 	return (0);
1572 }
1573 
1574 int
1575 read_queues(void)
1576 {
1577 	num_disp = num_queues = 0;
1578 
1579 	if (pfctl_update_qstats() < 0)
1580 		return (-1);
1581 	num_disp = num_queues;
1582 
1583 	return(0);
1584 }
1585 
1586 double
1587 calc_interval(struct timeval *cur_time, struct timeval *last_time)
1588 {
1589 	double	sec;
1590 
1591 	sec = (double)(cur_time->tv_sec - last_time->tv_sec) +
1592 	    (double)(cur_time->tv_usec - last_time->tv_usec) / 1000000;
1593 
1594 	return (sec);
1595 }
1596 
1597 double
1598 calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval)
1599 {
1600 	double	rate;
1601 
1602 	rate = (double)(new_bytes - last_bytes) / interval;
1603 	return (rate);
1604 }
1605 
1606 double
1607 calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval)
1608 {
1609 	double	pps;
1610 
1611 	pps = (double)(new_pkts - last_pkts) / interval;
1612 	return (pps);
1613 }
1614 
1615 void
1616 print_queue_node(struct pfctl_queue_node *node)
1617 {
1618 	u_int	rate;
1619 	int 	i;
1620 	double	interval, pps, bps;
1621 	static const char unit[] = " KMG";
1622 
1623 	tb_start();
1624 	for (i = 0; i < node->depth; i++)
1625 		tbprintf(" ");
1626 	tbprintf("%s", node->qs.qname);
1627 	if (i == 0 && node->qs.ifname[0])
1628 		tbprintf(" on %s ", node->qs.ifname);
1629 	print_fld_tb(FLD_QUEUE);
1630 
1631 	// XXX: missing min, max, burst
1632 	tb_start();
1633 	rate = node->qs.linkshare.m2.absolute;
1634 	for (i = 0; rate >= 1000 && i <= 3; i++)
1635 		rate /= 1000;
1636 	tbprintf("%u%c", rate, unit[i]);
1637 	print_fld_tb(FLD_BANDW);
1638 
1639 	if (node->qstats.valid && node->qstats_last.valid)
1640 		interval = calc_interval(&node->qstats.timestamp,
1641 		    &node->qstats_last.timestamp);
1642 	else
1643 		interval = 0;
1644 
1645 	print_fld_size(FLD_PKTS, node->qstats.data.xmit_cnt.packets);
1646 	print_fld_size(FLD_BYTES, node->qstats.data.xmit_cnt.bytes);
1647 	print_fld_size(FLD_DROPP, node->qstats.data.drop_cnt.packets);
1648 	print_fld_size(FLD_DROPB, node->qstats.data.drop_cnt.bytes);
1649 	print_fld_size(FLD_QLEN, node->qstats.data.qlength);
1650 
1651 	if (interval > 0) {
1652 		pps = calc_pps(node->qstats.data.xmit_cnt.packets,
1653 		    node->qstats_last.data.xmit_cnt.packets, interval);
1654 		bps = calc_rate(node->qstats.data.xmit_cnt.bytes,
1655 		    node->qstats_last.data.xmit_cnt.bytes, interval);
1656 
1657 		tb_start();
1658 		if (pps > 0 && pps < 1)
1659 			tbprintf("%-3.1lf", pps);
1660 		else
1661 			tbprintf("%u", (unsigned int)pps);
1662 
1663 		print_fld_tb(FLD_PKTSPS);
1664 		print_fld_bw(FLD_BYTESPS, bps);
1665 	}
1666 }
1667 
1668 void
1669 print_queues(void)
1670 {
1671 	uint32_t n, count, start;
1672 	struct pfctl_queue_node *node;
1673 
1674 	n = count = 0;
1675 	start = dispstart;
1676 
1677 	TAILQ_FOREACH(node, &qnodes, entries) {
1678 		if (n < start) {
1679 			n++;
1680 			continue;
1681 		}
1682 		print_queue_node(node);
1683 		end_line();
1684 		count++;
1685 		if (maxprint > 0 && count >= maxprint)
1686 			return;
1687 	}
1688 }
1689 
1690 /* main program functions */
1691 
1692 void
1693 update_cache(void)
1694 {
1695 	static int pstate = -1;
1696 	if (pstate == cachestates)
1697 		return;
1698 
1699 	pstate = cachestates;
1700 	if (cachestates) {
1701 		show_field(FLD_SI);
1702 		show_field(FLD_SP);
1703 		gotsig_alarm = 1;
1704 	} else {
1705 		hide_field(FLD_SI);
1706 		hide_field(FLD_SP);
1707 		need_update = 1;
1708 	}
1709 	field_setup();
1710 }
1711 
1712 int
1713 initpftop(void)
1714 {
1715 	struct pf_status status;
1716 	field_view *v;
1717 	int cachesize = DEFAULT_CACHE_SIZE;
1718 
1719 	v = views;
1720 	while(v->name != NULL)
1721 		add_view(v++);
1722 
1723 	pf_dev = open("/dev/pf", O_RDONLY);
1724 	if (pf_dev == -1) {
1725 		alloc_buf(0);
1726 	} else if (ioctl(pf_dev, DIOCGETSTATUS, &status)) {
1727 		warn("DIOCGETSTATUS");
1728 		alloc_buf(0);
1729 	} else
1730 		alloc_buf(status.states);
1731 
1732 	/* initialize cache with given size */
1733 	if (cache_init(cachesize))
1734 		warnx("Failed to initialize cache.");
1735 	else if (interactive && cachesize > 0)
1736 		cachestates = 1;
1737 
1738 	update_cache();
1739 
1740 	show_field(FLD_STMAX);
1741 	show_field(FLD_ANCHOR);
1742 
1743 	return (1);
1744 }
1745