GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/pftop.c Lines: 0 759 0.0 %
Date: 2017-11-07 Branches: 0 571 0.0 %

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