1*603ea060Sjsg /* $OpenBSD: pftop.c,v 1.47 2024/04/22 14:19:48 jsg Exp $ */
273baed14Scanacar /*
373baed14Scanacar * Copyright (c) 2001, 2007 Can Erkin Acar
473baed14Scanacar * Copyright (c) 2001 Daniel Hartmeier
573baed14Scanacar * All rights reserved.
673baed14Scanacar *
773baed14Scanacar * Redistribution and use in source and binary forms, with or without
873baed14Scanacar * modification, are permitted provided that the following conditions
973baed14Scanacar * are met:
1073baed14Scanacar *
1173baed14Scanacar * - Redistributions of source code must retain the above copyright
1273baed14Scanacar * notice, this list of conditions and the following disclaimer.
1373baed14Scanacar * - Redistributions in binary form must reproduce the above
1473baed14Scanacar * copyright notice, this list of conditions and the following
1573baed14Scanacar * disclaimer in the documentation and/or other materials provided
1673baed14Scanacar * with the distribution.
1773baed14Scanacar *
1873baed14Scanacar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1973baed14Scanacar * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2073baed14Scanacar * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2173baed14Scanacar * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2273baed14Scanacar * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2373baed14Scanacar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2473baed14Scanacar * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2573baed14Scanacar * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2673baed14Scanacar * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2773baed14Scanacar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2873baed14Scanacar * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2973baed14Scanacar * POSSIBILITY OF SUCH DAMAGE.
3073baed14Scanacar *
3173baed14Scanacar */
3273baed14Scanacar
3373baed14Scanacar #include <sys/types.h>
3473baed14Scanacar #include <sys/ioctl.h>
3573baed14Scanacar #include <sys/socket.h>
3673baed14Scanacar
3773baed14Scanacar #include <net/if.h>
3873baed14Scanacar #include <netinet/in.h>
3926f2f421Smcbride #include <netinet/tcp.h>
4073baed14Scanacar #include <netinet/tcp_fsm.h>
4173baed14Scanacar #include <net/pfvar.h>
4273baed14Scanacar #include <arpa/inet.h>
4373baed14Scanacar
44aa14b181Shenning #include <net/hfsc.h>
45aa14b181Shenning
4673baed14Scanacar #include <ctype.h>
4773baed14Scanacar #include <curses.h>
4873baed14Scanacar #include <err.h>
4973baed14Scanacar #include <errno.h>
5073baed14Scanacar #include <fcntl.h>
5173baed14Scanacar #include <netdb.h>
5273baed14Scanacar #include <signal.h>
5373baed14Scanacar #include <stdio.h>
5473baed14Scanacar #include <stdlib.h>
5573baed14Scanacar #include <string.h>
5673baed14Scanacar #include <unistd.h>
578f6b3bafSderaadt #include <limits.h>
5873baed14Scanacar #include <stdarg.h>
5973baed14Scanacar
60b1d2a504Scanacar #include "systat.h"
6173baed14Scanacar #include "engine.h"
6273baed14Scanacar #include "cache.h"
6373baed14Scanacar
6473baed14Scanacar extern const char *tcpstates[];
6573baed14Scanacar
6673baed14Scanacar #define MIN_NUM_STATES 1024
6773baed14Scanacar #define NUM_STATE_INC 1024
6873baed14Scanacar
6973baed14Scanacar #define DEFAULT_CACHE_SIZE 10000
7073baed14Scanacar
7173baed14Scanacar /* XXX must also check type before use */
7273baed14Scanacar #define PT_ADDR(x) (&(x)->addr.v.a.addr)
7373baed14Scanacar
7473baed14Scanacar /* XXX must also check type before use */
7573baed14Scanacar #define PT_MASK(x) (&(x)->addr.v.a.mask)
7673baed14Scanacar
7773baed14Scanacar #define PT_NOROUTE(x) ((x)->addr.type == PF_ADDR_NOROUTE)
7873baed14Scanacar
7973baed14Scanacar /* view management */
8073baed14Scanacar int select_states(void);
8173baed14Scanacar int read_states(void);
8273baed14Scanacar void sort_states(void);
8373baed14Scanacar void print_states(void);
8473baed14Scanacar
8573baed14Scanacar int select_rules(void);
8673baed14Scanacar int read_rules(void);
8773baed14Scanacar void print_rules(void);
8873baed14Scanacar
8973baed14Scanacar int select_queues(void);
9073baed14Scanacar int read_queues(void);
9173baed14Scanacar void print_queues(void);
9273baed14Scanacar
93035d703dScanacar void update_cache(void);
94035d703dScanacar
9573baed14Scanacar /* qsort callbacks */
9673baed14Scanacar int sort_size_callback(const void *s1, const void *s2);
9773baed14Scanacar int sort_exp_callback(const void *s1, const void *s2);
9873baed14Scanacar int sort_pkt_callback(const void *s1, const void *s2);
9973baed14Scanacar int sort_age_callback(const void *s1, const void *s2);
10073baed14Scanacar int sort_sa_callback(const void *s1, const void *s2);
10173baed14Scanacar int sort_sp_callback(const void *s1, const void *s2);
10273baed14Scanacar int sort_da_callback(const void *s1, const void *s2);
10373baed14Scanacar int sort_dp_callback(const void *s1, const void *s2);
10473baed14Scanacar int sort_rate_callback(const void *s1, const void *s2);
10573baed14Scanacar int sort_peak_callback(const void *s1, const void *s2);
10673baed14Scanacar int pf_dev = -1;
10773baed14Scanacar
10873baed14Scanacar struct sc_ent **state_cache = NULL;
109d93808b7Scanacar struct pfsync_state *state_buf = NULL;
1104c82f412Sbluhm size_t state_buf_len = 0;
1114c82f412Sbluhm size_t *state_ord = NULL;
1124c82f412Sbluhm size_t num_states = 0;
1134c82f412Sbluhm size_t num_states_all = 0;
11473baed14Scanacar u_int32_t num_rules = 0;
11573baed14Scanacar u_int32_t num_queues = 0;
11673baed14Scanacar int cachestates = 0;
11773baed14Scanacar
11873baed14Scanacar char *filter_string = NULL;
11973baed14Scanacar
12073baed14Scanacar #define MIN_LABEL_SIZE 5
12173baed14Scanacar #define ANCHOR_FLD_SIZE 12
12273baed14Scanacar
12373baed14Scanacar /* Define fields */
12473baed14Scanacar field_def fields[] = {
12573baed14Scanacar {"SRC", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
12673baed14Scanacar {"DEST", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
12773baed14Scanacar {"GW", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
12873baed14Scanacar {"STATE", 5, 23, 18, FLD_ALIGN_COLUMN, -1, 0, 0, 0},
12973baed14Scanacar {"AGE", 5, 9, 4, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13073baed14Scanacar {"EXP", 5, 9, 4, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13173baed14Scanacar {"PR ", 4, 9, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
13273baed14Scanacar {"DIR", 1, 3, 2, FLD_ALIGN_CENTER, -1, 0, 0, 0},
13373baed14Scanacar {"PKTS", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13473baed14Scanacar {"BYTES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13573baed14Scanacar {"RULE", 2, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13673baed14Scanacar {"LABEL", MIN_LABEL_SIZE, MIN_LABEL_SIZE, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
13773baed14Scanacar {"STATES", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13873baed14Scanacar {"EVAL", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
13973baed14Scanacar {"ACTION", 1, 8, 4, FLD_ALIGN_LEFT, -1, 0, 0, 0},
14073baed14Scanacar {"LOG", 1, 3, 2, FLD_ALIGN_LEFT, -1, 0, 0, 0},
14173baed14Scanacar {"QUICK", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
14273baed14Scanacar {"KS", 1, 1, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
143076a12fbSjasper {"IF", 4, 7, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
14473baed14Scanacar {"INFO", 40, 80, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
145d93808b7Scanacar {"MAX", 3, 5, 2, FLD_ALIGN_RIGHT, -1, 0, 0},
14673baed14Scanacar {"RATE", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
14773baed14Scanacar {"AVG", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
14873baed14Scanacar {"PEAK", 5, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
149d93808b7Scanacar {"ANCHOR", 6, 16, 1, FLD_ALIGN_LEFT, -1, 0, 0},
15073baed14Scanacar {"QUEUE", 15, 30, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
1516cb74e26Smikeb {"BW/FL", 4, 5, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15273baed14Scanacar {"SCH", 3, 4, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
15373baed14Scanacar {"DROP_P", 6, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15473baed14Scanacar {"DROP_B", 6, 8, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15573baed14Scanacar {"QLEN", 4, 4, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15673baed14Scanacar {"BORROW", 4, 6, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15773baed14Scanacar {"SUSPENDS", 4, 6, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15873baed14Scanacar {"P/S", 3, 7, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
15973baed14Scanacar {"B/S", 4, 7, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0}
16073baed14Scanacar };
16173baed14Scanacar
16273baed14Scanacar
16373baed14Scanacar /* for states */
164596a8091Sjasper #define FLD_SRC FIELD_ADDR(fields,0)
165596a8091Sjasper #define FLD_DEST FIELD_ADDR(fields,1)
166596a8091Sjasper #define FLD_GW FIELD_ADDR(fields,2)
167596a8091Sjasper #define FLD_STATE FIELD_ADDR(fields,3)
168596a8091Sjasper #define FLD_AGE FIELD_ADDR(fields,4)
169596a8091Sjasper #define FLD_EXP FIELD_ADDR(fields,5)
17073baed14Scanacar /* common */
171596a8091Sjasper #define FLD_PROTO FIELD_ADDR(fields,6)
172596a8091Sjasper #define FLD_DIR FIELD_ADDR(fields,7)
173596a8091Sjasper #define FLD_PKTS FIELD_ADDR(fields,8)
174596a8091Sjasper #define FLD_BYTES FIELD_ADDR(fields,9)
175596a8091Sjasper #define FLD_RULE FIELD_ADDR(fields,10)
17673baed14Scanacar /* for rules */
177596a8091Sjasper #define FLD_LABEL FIELD_ADDR(fields,11)
178596a8091Sjasper #define FLD_STATS FIELD_ADDR(fields,12)
179596a8091Sjasper #define FLD_EVAL FIELD_ADDR(fields,13)
180596a8091Sjasper #define FLD_ACTION FIELD_ADDR(fields,14)
181596a8091Sjasper #define FLD_LOG FIELD_ADDR(fields,15)
182596a8091Sjasper #define FLD_QUICK FIELD_ADDR(fields,16)
183596a8091Sjasper #define FLD_KST FIELD_ADDR(fields,17)
184596a8091Sjasper #define FLD_IF FIELD_ADDR(fields,18)
185596a8091Sjasper #define FLD_RINFO FIELD_ADDR(fields,19)
186596a8091Sjasper #define FLD_STMAX FIELD_ADDR(fields,20)
18773baed14Scanacar /* other */
188596a8091Sjasper #define FLD_SI FIELD_ADDR(fields,21) /* instantaneous speed */
189596a8091Sjasper #define FLD_SA FIELD_ADDR(fields,22) /* average speed */
190596a8091Sjasper #define FLD_SP FIELD_ADDR(fields,23) /* peak speed */
191596a8091Sjasper #define FLD_ANCHOR FIELD_ADDR(fields,24)
19273baed14Scanacar /* for queues */
193596a8091Sjasper #define FLD_QUEUE FIELD_ADDR(fields,25)
194596a8091Sjasper #define FLD_BANDW FIELD_ADDR(fields,26)
195596a8091Sjasper #define FLD_SCHED FIELD_ADDR(fields,27)
19675cf0799Smikeb #define FLD_DROPP FIELD_ADDR(fields,28)
19775cf0799Smikeb #define FLD_DROPB FIELD_ADDR(fields,29)
19875cf0799Smikeb #define FLD_QLEN FIELD_ADDR(fields,30)
19975cf0799Smikeb #define FLD_BORR FIELD_ADDR(fields,31)
20075cf0799Smikeb #define FLD_SUSP FIELD_ADDR(fields,32)
20175cf0799Smikeb #define FLD_PKTSPS FIELD_ADDR(fields,33)
20275cf0799Smikeb #define FLD_BYTESPS FIELD_ADDR(fields,34)
20373baed14Scanacar
20473baed14Scanacar /* Define views */
20573baed14Scanacar field_def *view0[] = {
20673baed14Scanacar FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_STATE,
20773baed14Scanacar FLD_AGE, FLD_EXP, FLD_PKTS, FLD_BYTES, NULL
20873baed14Scanacar };
20973baed14Scanacar
21073baed14Scanacar field_def *view1[] = {
21173baed14Scanacar FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_GW, FLD_STATE, FLD_AGE,
21273baed14Scanacar FLD_EXP, FLD_PKTS, FLD_BYTES, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, NULL
21373baed14Scanacar };
21473baed14Scanacar
21573baed14Scanacar field_def *view2[] = {
21673baed14Scanacar FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_STATE, FLD_AGE, FLD_EXP,
21773baed14Scanacar FLD_PKTS, FLD_BYTES, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
21873baed14Scanacar };
21973baed14Scanacar
22073baed14Scanacar field_def *view3[] = {
22173baed14Scanacar FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_AGE, FLD_EXP, FLD_PKTS,
22273baed14Scanacar FLD_BYTES, FLD_STATE, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
22373baed14Scanacar };
22473baed14Scanacar
22573baed14Scanacar field_def *view4[] = {
22673baed14Scanacar FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_PKTS, FLD_BYTES, FLD_STATE,
22773baed14Scanacar FLD_AGE, FLD_EXP, FLD_SI, FLD_SP, FLD_SA, FLD_RULE, FLD_GW, NULL
22873baed14Scanacar };
22973baed14Scanacar
23073baed14Scanacar field_def *view5[] = {
23173baed14Scanacar FLD_RULE, FLD_ANCHOR, FLD_ACTION, FLD_DIR, FLD_LOG, FLD_QUICK, FLD_IF,
23273baed14Scanacar FLD_PROTO, FLD_KST, FLD_PKTS, FLD_BYTES, FLD_STATS, FLD_STMAX,
23373baed14Scanacar FLD_RINFO, NULL
23473baed14Scanacar };
23573baed14Scanacar
23673baed14Scanacar field_def *view6[] = {
23773baed14Scanacar FLD_RULE, FLD_LABEL, FLD_PKTS, FLD_BYTES, FLD_STATS, FLD_STMAX,
23873baed14Scanacar FLD_ACTION, FLD_DIR, FLD_LOG, FLD_QUICK, FLD_IF, FLD_PROTO,
23973baed14Scanacar FLD_ANCHOR, FLD_KST, NULL
24073baed14Scanacar };
24173baed14Scanacar
24273baed14Scanacar field_def *view7[] = {
24373baed14Scanacar FLD_PROTO, FLD_DIR, FLD_SRC, FLD_DEST, FLD_SI, FLD_SP, FLD_SA,
24473baed14Scanacar FLD_BYTES, FLD_STATE, FLD_PKTS, FLD_AGE, FLD_EXP, FLD_RULE, FLD_GW, NULL
24573baed14Scanacar };
24673baed14Scanacar
24773baed14Scanacar field_def *view8[] = {
24875cf0799Smikeb FLD_QUEUE, FLD_BANDW, FLD_SCHED, FLD_PKTS, FLD_BYTES,
24973baed14Scanacar FLD_DROPP, FLD_DROPB, FLD_QLEN, FLD_BORR, FLD_SUSP, FLD_PKTSPS,
25073baed14Scanacar FLD_BYTESPS, NULL
25173baed14Scanacar };
25273baed14Scanacar
25373baed14Scanacar /* Define orderings */
25473baed14Scanacar order_type order_list[] = {
25573baed14Scanacar {"none", "none", 'N', NULL},
25673baed14Scanacar {"bytes", "bytes", 'B', sort_size_callback},
25773baed14Scanacar {"expiry", "exp", 'E', sort_exp_callback},
25873baed14Scanacar {"packets", "pkt", 'P', sort_pkt_callback},
25973baed14Scanacar {"age", "age", 'A', sort_age_callback},
26073baed14Scanacar {"source addr", "src", 'F', sort_sa_callback},
26173baed14Scanacar {"dest. addr", "dest", 'T', sort_da_callback},
26273baed14Scanacar {"source port", "sport", 'S', sort_sp_callback},
26373baed14Scanacar {"dest. port", "dport", 'D', sort_dp_callback},
26473baed14Scanacar {"rate", "rate", 'R', sort_rate_callback},
26573baed14Scanacar {"peak", "peak", 'K', sort_peak_callback},
26673baed14Scanacar {NULL, NULL, 0, NULL}
26773baed14Scanacar };
26873baed14Scanacar
26973baed14Scanacar /* Define view managers */
27073baed14Scanacar struct view_manager state_mgr = {
27173baed14Scanacar "States", select_states, read_states, sort_states, print_header,
2728d6a960aSmartijn print_states, keyboard_callback, order_list, order_list
27373baed14Scanacar };
27473baed14Scanacar
27573baed14Scanacar struct view_manager rule_mgr = {
27673baed14Scanacar "Rules", select_rules, read_rules, NULL, print_header,
27773baed14Scanacar print_rules, keyboard_callback, NULL, NULL
27873baed14Scanacar };
27973baed14Scanacar
28073baed14Scanacar struct view_manager queue_mgr = {
28173baed14Scanacar "Queues", select_queues, read_queues, NULL, print_header,
28273baed14Scanacar print_queues, keyboard_callback, NULL, NULL
28373baed14Scanacar };
28473baed14Scanacar
28573baed14Scanacar field_view views[] = {
28673baed14Scanacar {view2, "states", '8', &state_mgr},
28773baed14Scanacar {view5, "rules", '9', &rule_mgr},
28873baed14Scanacar {view8, "queues", 'Q', &queue_mgr},
28973baed14Scanacar {NULL, NULL, 0, NULL}
29073baed14Scanacar };
29173baed14Scanacar
292aa14b181Shenning /* queue structures from pfctl */
293aa14b181Shenning
294aa14b181Shenning struct queue_stats {
295aa14b181Shenning struct hfsc_class_stats data;
296aa14b181Shenning int valid;
297aa14b181Shenning struct timeval timestamp;
298aa14b181Shenning };
299aa14b181Shenning
300aa14b181Shenning struct pfctl_queue_node {
301aa14b181Shenning TAILQ_ENTRY(pfctl_queue_node) entries;
302aa14b181Shenning struct pf_queuespec qs;
303aa14b181Shenning struct queue_stats qstats;
304aa14b181Shenning struct queue_stats qstats_last;
305aa14b181Shenning int depth;
306aa14b181Shenning };
307aa14b181Shenning TAILQ_HEAD(qnodes, pfctl_queue_node) qnodes = TAILQ_HEAD_INITIALIZER(qnodes);
30873baed14Scanacar
30973baed14Scanacar /* ordering functions */
31073baed14Scanacar
31173baed14Scanacar int
sort_size_callback(const void * s1,const void * s2)31273baed14Scanacar sort_size_callback(const void *s1, const void *s2)
31373baed14Scanacar {
3144c82f412Sbluhm u_int64_t b1 = COUNTER(state_buf[* (size_t *) s1].bytes[0]) +
3154c82f412Sbluhm COUNTER(state_buf[* (size_t *) s1].bytes[1]);
3164c82f412Sbluhm u_int64_t b2 = COUNTER(state_buf[* (size_t *) s2].bytes[0]) +
3174c82f412Sbluhm COUNTER(state_buf[* (size_t *) s2].bytes[1]);
31873baed14Scanacar if (b2 > b1)
31973baed14Scanacar return sortdir;
32073baed14Scanacar if (b2 < b1)
32173baed14Scanacar return -sortdir;
32273baed14Scanacar return 0;
32373baed14Scanacar }
32473baed14Scanacar
32573baed14Scanacar int
sort_pkt_callback(const void * s1,const void * s2)32673baed14Scanacar sort_pkt_callback(const void *s1, const void *s2)
32773baed14Scanacar {
3284c82f412Sbluhm u_int64_t p1 = COUNTER(state_buf[* (size_t *) s1].packets[0]) +
3294c82f412Sbluhm COUNTER(state_buf[* (size_t *) s1].packets[1]);
3304c82f412Sbluhm u_int64_t p2 = COUNTER(state_buf[* (size_t *) s2].packets[0]) +
3314c82f412Sbluhm COUNTER(state_buf[* (size_t *) s2].packets[1]);
33273baed14Scanacar if (p2 > p1)
33373baed14Scanacar return sortdir;
33473baed14Scanacar if (p2 < p1)
33573baed14Scanacar return -sortdir;
33673baed14Scanacar return 0;
33773baed14Scanacar }
33873baed14Scanacar
33973baed14Scanacar int
sort_age_callback(const void * s1,const void * s2)34073baed14Scanacar sort_age_callback(const void *s1, const void *s2)
34173baed14Scanacar {
3424c82f412Sbluhm if (ntohl(state_buf[* (size_t *) s2].creation) >
3434c82f412Sbluhm ntohl(state_buf[* (size_t *) s1].creation))
34473baed14Scanacar return sortdir;
3454c82f412Sbluhm if (ntohl(state_buf[* (size_t *) s2].creation) <
3464c82f412Sbluhm ntohl(state_buf[* (size_t *) s1].creation))
34773baed14Scanacar return -sortdir;
34873baed14Scanacar return 0;
34973baed14Scanacar }
35073baed14Scanacar
35173baed14Scanacar int
sort_exp_callback(const void * s1,const void * s2)35273baed14Scanacar sort_exp_callback(const void *s1, const void *s2)
35373baed14Scanacar {
3544c82f412Sbluhm if (ntohl(state_buf[* (size_t *) s2].expire) >
3554c82f412Sbluhm ntohl(state_buf[* (size_t *) s1].expire))
35673baed14Scanacar return sortdir;
3574c82f412Sbluhm if (ntohl(state_buf[* (size_t *) s2].expire) <
3584c82f412Sbluhm ntohl(state_buf[* (size_t *) s1].expire))
35973baed14Scanacar return -sortdir;
36073baed14Scanacar return 0;
36173baed14Scanacar }
36273baed14Scanacar
36373baed14Scanacar int
sort_rate_callback(const void * s1,const void * s2)36473baed14Scanacar sort_rate_callback(const void *s1, const void *s2)
36573baed14Scanacar {
36673baed14Scanacar struct sc_ent *e1 = state_cache[* (u_int32_t *) s1];
36773baed14Scanacar struct sc_ent *e2 = state_cache[* (u_int32_t *) s2];
36873baed14Scanacar
36973baed14Scanacar if (e1 == NULL)
37073baed14Scanacar return sortdir;
37173baed14Scanacar if (e2 == NULL)
37273baed14Scanacar return -sortdir;
37373baed14Scanacar
37473baed14Scanacar if (e2->rate > e1 -> rate)
37573baed14Scanacar return sortdir;
37673baed14Scanacar if (e2->rate < e1 -> rate)
37773baed14Scanacar return -sortdir;
37873baed14Scanacar return 0;
37973baed14Scanacar }
38073baed14Scanacar
38173baed14Scanacar int
sort_peak_callback(const void * s1,const void * s2)38273baed14Scanacar sort_peak_callback(const void *s1, const void *s2)
38373baed14Scanacar {
38473baed14Scanacar struct sc_ent *e1 = state_cache[* (u_int32_t *) s1];
38573baed14Scanacar struct sc_ent *e2 = state_cache[* (u_int32_t *) s2];
38673baed14Scanacar
38773baed14Scanacar if (e2 == NULL)
38873baed14Scanacar return -sortdir;
38973baed14Scanacar if (e1 == NULL || e2 == NULL)
39073baed14Scanacar return 0;
39173baed14Scanacar
39273baed14Scanacar if (e2->peak > e1 -> peak)
39373baed14Scanacar return sortdir;
39473baed14Scanacar if (e2->peak < e1 -> peak)
39573baed14Scanacar return -sortdir;
39673baed14Scanacar return 0;
39773baed14Scanacar }
39873baed14Scanacar
39973baed14Scanacar int
compare_addr(int af,const struct pf_addr * a,const struct pf_addr * b)40073baed14Scanacar compare_addr(int af, const struct pf_addr *a, const struct pf_addr *b)
40173baed14Scanacar {
40273baed14Scanacar switch (af) {
40373baed14Scanacar case AF_INET:
40473baed14Scanacar if (ntohl(a->addr32[0]) > ntohl(b->addr32[0]))
40573baed14Scanacar return 1;
40673baed14Scanacar if (a->addr32[0] != b->addr32[0])
40773baed14Scanacar return -1;
40873baed14Scanacar break;
40973baed14Scanacar case AF_INET6:
41073baed14Scanacar if (ntohl(a->addr32[0]) > ntohl(b->addr32[0]))
41173baed14Scanacar return 1;
41273baed14Scanacar if (a->addr32[0] != b->addr32[0])
41373baed14Scanacar return -1;
41473baed14Scanacar if (ntohl(a->addr32[1]) > ntohl(b->addr32[1]))
41573baed14Scanacar return 1;
41673baed14Scanacar if (a->addr32[1] != b->addr32[1])
41773baed14Scanacar return -1;
41873baed14Scanacar if (ntohl(a->addr32[2]) > ntohl(b->addr32[2]))
41973baed14Scanacar return 1;
42073baed14Scanacar if (a->addr32[2] != b->addr32[2])
42173baed14Scanacar return -1;
42273baed14Scanacar if (ntohl(a->addr32[3]) > ntohl(b->addr32[3]))
42373baed14Scanacar return 1;
42473baed14Scanacar if (a->addr32[3] != b->addr32[3])
42573baed14Scanacar return -1;
42673baed14Scanacar break;
42773baed14Scanacar }
42873baed14Scanacar
42973baed14Scanacar return 0;
43073baed14Scanacar }
43173baed14Scanacar
43238bde8c5Sjsg static __inline int
sort_addr_callback(const struct pfsync_state * s1,const struct pfsync_state * s2,int dir)433d93808b7Scanacar sort_addr_callback(const struct pfsync_state *s1,
434d93808b7Scanacar const struct pfsync_state *s2, int dir)
43573baed14Scanacar {
43673baed14Scanacar const struct pf_addr *aa, *ab;
43773baed14Scanacar u_int16_t pa, pb;
438d25344e8Sclaudio int af, side, ret, ii, io;
43973baed14Scanacar
440d25344e8Sclaudio side = s1->direction == PF_IN ? PF_SK_STACK : PF_SK_WIRE;
44173baed14Scanacar
442d25344e8Sclaudio if (s1->key[side].af > s2->key[side].af)
44373baed14Scanacar return sortdir;
444d25344e8Sclaudio if (s1->key[side].af < s2->key[side].af)
44573baed14Scanacar return -sortdir;
44673baed14Scanacar
44773baed14Scanacar ii = io = 0;
44873baed14Scanacar
44973baed14Scanacar if (dir == PF_OUT) /* looking for source addr */
45073baed14Scanacar io = 1;
45173baed14Scanacar else /* looking for dest addr */
45273baed14Scanacar ii = 1;
45373baed14Scanacar
454d25344e8Sclaudio if (s1->key[PF_SK_STACK].af != s1->key[PF_SK_WIRE].af) {
455d25344e8Sclaudio dir = PF_OUT;
456d25344e8Sclaudio side = PF_SK_STACK;
45773baed14Scanacar } else {
458d25344e8Sclaudio dir = s1->direction;
459d25344e8Sclaudio side = PF_SK_WIRE;
46073baed14Scanacar }
46173baed14Scanacar
462d25344e8Sclaudio if (dir == PF_IN) {
463d25344e8Sclaudio aa = &s1->key[PF_SK_STACK].addr[ii];
464d25344e8Sclaudio pa = s1->key[PF_SK_STACK].port[ii];
465d25344e8Sclaudio af = s1->key[PF_SK_STACK].af;
466d25344e8Sclaudio } else {
467d25344e8Sclaudio aa = &s1->key[side].addr[io];
468d25344e8Sclaudio pa = s1->key[side].port[io];
469d25344e8Sclaudio af = s1->key[side].af;
470d25344e8Sclaudio }
471d25344e8Sclaudio
472d25344e8Sclaudio if (s2->key[PF_SK_STACK].af != s2->key[PF_SK_WIRE].af) {
473d25344e8Sclaudio dir = PF_OUT;
474d25344e8Sclaudio side = PF_SK_STACK;
475d25344e8Sclaudio } else {
476d25344e8Sclaudio dir = s2->direction;
477d25344e8Sclaudio side = PF_SK_WIRE;
478d25344e8Sclaudio }
479d25344e8Sclaudio
480d25344e8Sclaudio if (dir == PF_IN) {
481969c2abfSderaadt ab = &s2->key[PF_SK_STACK].addr[ii];
48273baed14Scanacar pb = s2->key[PF_SK_STACK].port[ii];
483d25344e8Sclaudio af = s1->key[PF_SK_STACK].af;
48473baed14Scanacar } else {
485d25344e8Sclaudio ab = &s2->key[side].addr[io];
486d25344e8Sclaudio pb = s2->key[side].port[io];
487d25344e8Sclaudio af = s1->key[side].af;
48873baed14Scanacar }
48973baed14Scanacar
49073baed14Scanacar ret = compare_addr(af, aa, ab);
49173baed14Scanacar if (ret)
49273baed14Scanacar return ret * sortdir;
49373baed14Scanacar
49473baed14Scanacar if (ntohs(pa) > ntohs(pb))
49573baed14Scanacar return sortdir;
49673baed14Scanacar return -sortdir;
49773baed14Scanacar }
49873baed14Scanacar
49938bde8c5Sjsg static __inline int
sort_port_callback(const struct pfsync_state * s1,const struct pfsync_state * s2,int dir)500d93808b7Scanacar sort_port_callback(const struct pfsync_state *s1,
501d93808b7Scanacar const struct pfsync_state *s2, int dir)
50273baed14Scanacar {
50373baed14Scanacar const struct pf_addr *aa, *ab;
50473baed14Scanacar u_int16_t pa, pb;
505d25344e8Sclaudio int af, side, ret, ii, io;
50673baed14Scanacar
507d25344e8Sclaudio side = s1->direction == PF_IN ? PF_SK_STACK : PF_SK_WIRE;
50873baed14Scanacar
509d25344e8Sclaudio if (s1->key[side].af > s2->key[side].af)
51073baed14Scanacar return sortdir;
511d25344e8Sclaudio if (s1->key[side].af < s2->key[side].af)
51273baed14Scanacar return -sortdir;
51373baed14Scanacar
51473baed14Scanacar ii = io = 0;
51573baed14Scanacar
51673baed14Scanacar if (dir == PF_OUT) /* looking for source addr */
51773baed14Scanacar io = 1;
51873baed14Scanacar else /* looking for dest addr */
51973baed14Scanacar ii = 1;
52073baed14Scanacar
521d25344e8Sclaudio if (s1->key[PF_SK_STACK].af != s1->key[PF_SK_WIRE].af) {
522d25344e8Sclaudio dir = PF_OUT;
523d25344e8Sclaudio side = PF_SK_STACK;
52473baed14Scanacar } else {
525d25344e8Sclaudio dir = s1->direction;
526d25344e8Sclaudio side = PF_SK_WIRE;
52773baed14Scanacar }
52873baed14Scanacar
529d25344e8Sclaudio if (dir == PF_IN) {
530d25344e8Sclaudio aa = &s1->key[PF_SK_STACK].addr[ii];
531d25344e8Sclaudio pa = s1->key[PF_SK_STACK].port[ii];
532d25344e8Sclaudio af = s1->key[PF_SK_STACK].af;
533d25344e8Sclaudio } else {
534d25344e8Sclaudio aa = &s1->key[side].addr[io];
535d25344e8Sclaudio pa = s1->key[side].port[io];
536d25344e8Sclaudio af = s1->key[side].af;
537d25344e8Sclaudio }
538d25344e8Sclaudio
539d25344e8Sclaudio if (s2->key[PF_SK_STACK].af != s2->key[PF_SK_WIRE].af) {
540d25344e8Sclaudio dir = PF_OUT;
541d25344e8Sclaudio side = PF_SK_STACK;
542d25344e8Sclaudio } else {
543d25344e8Sclaudio dir = s2->direction;
544d25344e8Sclaudio side = PF_SK_WIRE;
545d25344e8Sclaudio }
546d25344e8Sclaudio
547d25344e8Sclaudio if (dir == PF_IN) {
548969c2abfSderaadt ab = &s2->key[PF_SK_STACK].addr[ii];
54973baed14Scanacar pb = s2->key[PF_SK_STACK].port[ii];
550d25344e8Sclaudio af = s1->key[PF_SK_STACK].af;
55173baed14Scanacar } else {
552d25344e8Sclaudio ab = &s2->key[side].addr[io];
553d25344e8Sclaudio pb = s2->key[side].port[io];
554d25344e8Sclaudio af = s1->key[side].af;
55573baed14Scanacar }
55673baed14Scanacar
55773baed14Scanacar
55873baed14Scanacar if (ntohs(pa) > ntohs(pb))
55973baed14Scanacar return sortdir;
56073baed14Scanacar if (ntohs(pa) < ntohs(pb))
56173baed14Scanacar return - sortdir;
56273baed14Scanacar
56373baed14Scanacar ret = compare_addr(af, aa, ab);
56473baed14Scanacar if (ret)
56573baed14Scanacar return ret * sortdir;
56673baed14Scanacar return -sortdir;
56773baed14Scanacar }
56873baed14Scanacar
56973baed14Scanacar int
sort_sa_callback(const void * p1,const void * p2)570d93808b7Scanacar sort_sa_callback(const void *p1, const void *p2)
57173baed14Scanacar {
5724c82f412Sbluhm struct pfsync_state *s1 = state_buf + (* (size_t *) p1);
5734c82f412Sbluhm struct pfsync_state *s2 = state_buf + (* (size_t *) p2);
57473baed14Scanacar return sort_addr_callback(s1, s2, PF_OUT);
57573baed14Scanacar }
57673baed14Scanacar
577d93808b7Scanacar int
sort_da_callback(const void * p1,const void * p2)578d93808b7Scanacar sort_da_callback(const void *p1, const void *p2)
57973baed14Scanacar {
5804c82f412Sbluhm struct pfsync_state *s1 = state_buf + (* (size_t *) p1);
5814c82f412Sbluhm struct pfsync_state *s2 = state_buf + (* (size_t *) p2);
58273baed14Scanacar return sort_addr_callback(s1, s2, PF_IN);
58373baed14Scanacar }
58473baed14Scanacar
58573baed14Scanacar int
sort_sp_callback(const void * p1,const void * p2)58673baed14Scanacar sort_sp_callback(const void *p1, const void *p2)
58773baed14Scanacar {
5884c82f412Sbluhm struct pfsync_state *s1 = state_buf + (* (size_t *) p1);
5894c82f412Sbluhm struct pfsync_state *s2 = state_buf + (* (size_t *) p2);
59073baed14Scanacar return sort_port_callback(s1, s2, PF_OUT);
59173baed14Scanacar }
59273baed14Scanacar
59373baed14Scanacar int
sort_dp_callback(const void * p1,const void * p2)59473baed14Scanacar sort_dp_callback(const void *p1, const void *p2)
59573baed14Scanacar {
5964c82f412Sbluhm struct pfsync_state *s1 = state_buf + (* (size_t *) p1);
5974c82f412Sbluhm struct pfsync_state *s2 = state_buf + (* (size_t *) p2);
59873baed14Scanacar return sort_port_callback(s1, s2, PF_IN);
59973baed14Scanacar }
60073baed14Scanacar
60173baed14Scanacar void
sort_states(void)60273baed14Scanacar sort_states(void)
60373baed14Scanacar {
60473baed14Scanacar order_type *ordering;
60573baed14Scanacar
60673baed14Scanacar if (curr_mgr == NULL)
60773baed14Scanacar return;
60873baed14Scanacar
60973baed14Scanacar ordering = curr_mgr->order_curr;
61073baed14Scanacar
61173baed14Scanacar if (ordering == NULL)
61273baed14Scanacar return;
61373baed14Scanacar if (ordering->func == NULL)
61473baed14Scanacar return;
61573baed14Scanacar if (state_buf == NULL)
61673baed14Scanacar return;
61773baed14Scanacar if (num_states <= 0)
61873baed14Scanacar return;
61973baed14Scanacar
6204c82f412Sbluhm mergesort(state_ord, num_states, sizeof(size_t), ordering->func);
62173baed14Scanacar }
62273baed14Scanacar
62373baed14Scanacar /* state management functions */
62473baed14Scanacar
62573baed14Scanacar void
alloc_buf(size_t ns)6264c82f412Sbluhm alloc_buf(size_t ns)
62773baed14Scanacar {
6284c82f412Sbluhm size_t len;
62973baed14Scanacar
63073baed14Scanacar if (ns < MIN_NUM_STATES)
63173baed14Scanacar ns = MIN_NUM_STATES;
63273baed14Scanacar
63373baed14Scanacar len = ns;
63473baed14Scanacar
63573baed14Scanacar if (len >= state_buf_len) {
63673baed14Scanacar len += NUM_STATE_INC;
6372daca27aSdoug state_buf = reallocarray(state_buf, len,
6382daca27aSdoug sizeof(struct pfsync_state));
6394c82f412Sbluhm state_ord = reallocarray(state_ord, len, sizeof(size_t));
6402daca27aSdoug state_cache = reallocarray(state_cache, len,
6412daca27aSdoug sizeof(struct sc_ent *));
64273baed14Scanacar if (state_buf == NULL || state_ord == NULL ||
64373baed14Scanacar state_cache == NULL)
64473baed14Scanacar err(1, "realloc");
64573baed14Scanacar state_buf_len = len;
64673baed14Scanacar }
64773baed14Scanacar }
64873baed14Scanacar
64973baed14Scanacar int
select_states(void)65073baed14Scanacar select_states(void)
65173baed14Scanacar {
65273baed14Scanacar num_disp = num_states;
65373baed14Scanacar return (0);
65473baed14Scanacar }
65573baed14Scanacar
65673baed14Scanacar int
read_states(void)65773baed14Scanacar read_states(void)
65873baed14Scanacar {
65973baed14Scanacar struct pfioc_states ps;
6604c82f412Sbluhm size_t n;
66173baed14Scanacar
66273baed14Scanacar if (pf_dev == -1)
66373baed14Scanacar return -1;
66473baed14Scanacar
66573baed14Scanacar for (;;) {
6664c82f412Sbluhm size_t sbytes = state_buf_len * sizeof(struct pfsync_state);
66773baed14Scanacar
66873baed14Scanacar ps.ps_len = sbytes;
6694c82f412Sbluhm ps.ps_states = state_buf;
67073baed14Scanacar
6713aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETSTATES, &ps) == -1) {
67273baed14Scanacar error("DIOCGETSTATES");
67373baed14Scanacar }
674d93808b7Scanacar num_states_all = ps.ps_len / sizeof(struct pfsync_state);
67573baed14Scanacar
67673baed14Scanacar if (ps.ps_len < sbytes)
67773baed14Scanacar break;
67873baed14Scanacar
67973baed14Scanacar alloc_buf(num_states_all);
68073baed14Scanacar }
68173baed14Scanacar
68273baed14Scanacar num_states = num_states_all;
68373baed14Scanacar for (n = 0; n < num_states_all; n++)
68473baed14Scanacar state_ord[n] = n;
68573baed14Scanacar
68673baed14Scanacar if (cachestates) {
68773baed14Scanacar for (n = 0; n < num_states; n++)
68873baed14Scanacar state_cache[n] = cache_state(state_buf + n);
68973baed14Scanacar cache_endupdate();
69073baed14Scanacar }
69173baed14Scanacar
69273baed14Scanacar num_disp = num_states;
69373baed14Scanacar return 0;
69473baed14Scanacar }
69573baed14Scanacar
69673baed14Scanacar int
unmask(struct pf_addr * m)697eaa84e12Skn unmask(struct pf_addr * m)
69873baed14Scanacar {
699eaa84e12Skn int i = 31, j = 0, b = 0;
70073baed14Scanacar u_int32_t tmp;
70173baed14Scanacar
702eaa84e12Skn while (j < 4 && m->addr32[j] == 0xffffffff) {
70373baed14Scanacar b += 32;
70473baed14Scanacar j++;
70573baed14Scanacar }
706eaa84e12Skn if (j < 4) {
70773baed14Scanacar tmp = ntohl(m->addr32[j]);
70873baed14Scanacar for (i = 31; tmp & (1 << i); --i)
70973baed14Scanacar b++;
71073baed14Scanacar }
71173baed14Scanacar return (b);
71273baed14Scanacar }
71373baed14Scanacar
71473baed14Scanacar /* display functions */
71573baed14Scanacar
71673baed14Scanacar void
tb_print_addr(struct pf_addr * addr,struct pf_addr * mask,int af)71773baed14Scanacar tb_print_addr(struct pf_addr * addr, struct pf_addr * mask, int af)
71873baed14Scanacar {
7190b1a326cSgiovanni switch (af) {
720*603ea060Sjsg case AF_INET:
7210b1a326cSgiovanni tbprintf("%s", inetname(addr->v4));
7220b1a326cSgiovanni break;
723*603ea060Sjsg case AF_INET6:
7240b1a326cSgiovanni tbprintf("%s", inet6name(&addr->v6));
7250b1a326cSgiovanni break;
7260b1a326cSgiovanni }
72773baed14Scanacar
72873baed14Scanacar if (mask != NULL) {
72973baed14Scanacar if (!PF_AZERO(mask, af))
730eaa84e12Skn tbprintf("/%u", unmask(mask));
73173baed14Scanacar }
73273baed14Scanacar }
733d93808b7Scanacar
73473baed14Scanacar void
print_fld_host2(field_def * fld,struct pfsync_state_key * ks,struct pfsync_state_key * kn,int idx)73573baed14Scanacar print_fld_host2(field_def *fld, struct pfsync_state_key *ks,
736d25344e8Sclaudio struct pfsync_state_key *kn, int idx)
73773baed14Scanacar {
73873baed14Scanacar struct pf_addr *as = &ks->addr[idx];
73973baed14Scanacar struct pf_addr *an = &kn->addr[idx];
74073baed14Scanacar
74173baed14Scanacar u_int16_t ps = ntohs(ks->port[idx]);
74273baed14Scanacar u_int16_t pn = ntohs(kn->port[idx]);
74373baed14Scanacar
744d25344e8Sclaudio int asf = ks->af;
745d25344e8Sclaudio int anf = kn->af;
746d25344e8Sclaudio
74773baed14Scanacar if (fld == NULL)
74873baed14Scanacar return;
74973baed14Scanacar
75073baed14Scanacar if (fld->width < 3) {
75173baed14Scanacar print_fld_str(fld, "*");
75273baed14Scanacar return;
75373baed14Scanacar }
75473baed14Scanacar
75573baed14Scanacar tb_start();
756d25344e8Sclaudio tb_print_addr(as, NULL, asf);
75773baed14Scanacar
758d25344e8Sclaudio if (asf == AF_INET)
75973baed14Scanacar tbprintf(":%u", ps);
76073baed14Scanacar else
76173baed14Scanacar tbprintf("[%u]", ps);
76273baed14Scanacar
76373baed14Scanacar print_fld_tb(fld);
76473baed14Scanacar
765d25344e8Sclaudio if (asf != anf || PF_ANEQ(as, an, asf) || ps != pn) {
76673baed14Scanacar tb_start();
767d25344e8Sclaudio tb_print_addr(an, NULL, anf);
76873baed14Scanacar
769d25344e8Sclaudio if (anf == AF_INET)
77073baed14Scanacar tbprintf(":%u", pn);
77173baed14Scanacar else
77273baed14Scanacar tbprintf("[%u]", pn);
77373baed14Scanacar print_fld_tb(FLD_GW);
77473baed14Scanacar }
77573baed14Scanacar
77673baed14Scanacar }
77773baed14Scanacar
77873baed14Scanacar void
print_fld_state(field_def * fld,unsigned int proto,unsigned int s1,unsigned int s2)77973baed14Scanacar print_fld_state(field_def *fld, unsigned int proto,
78073baed14Scanacar unsigned int s1, unsigned int s2)
78173baed14Scanacar {
78273baed14Scanacar int len;
78373baed14Scanacar
78473baed14Scanacar if (fld == NULL)
78573baed14Scanacar return;
78673baed14Scanacar
78773baed14Scanacar len = fld->width;
78873baed14Scanacar if (len < 1)
78973baed14Scanacar return;
79073baed14Scanacar
79173baed14Scanacar tb_start();
79273baed14Scanacar
79373baed14Scanacar if (proto == IPPROTO_TCP) {
79473baed14Scanacar if (s1 <= TCPS_TIME_WAIT && s2 <= TCPS_TIME_WAIT)
79573baed14Scanacar tbprintf("%s:%s", tcpstates[s1], tcpstates[s2]);
79673baed14Scanacar #ifdef PF_TCPS_PROXY_SRC
79773baed14Scanacar else if (s1 == PF_TCPS_PROXY_SRC ||
79873baed14Scanacar s2 == PF_TCPS_PROXY_SRC)
79973baed14Scanacar tbprintf("PROXY:SRC\n");
80073baed14Scanacar else if (s1 == PF_TCPS_PROXY_DST ||
80173baed14Scanacar s2 == PF_TCPS_PROXY_DST)
80273baed14Scanacar tbprintf("PROXY:DST\n");
80373baed14Scanacar #endif
80473baed14Scanacar else
80573baed14Scanacar tbprintf("<BAD STATE LEVELS>");
80673baed14Scanacar } else if (proto == IPPROTO_UDP && s1 < PFUDPS_NSTATES &&
80773baed14Scanacar s2 < PFUDPS_NSTATES) {
80873baed14Scanacar const char *states[] = PFUDPS_NAMES;
80973baed14Scanacar tbprintf("%s:%s", states[s1], states[s2]);
81073baed14Scanacar } else if (proto != IPPROTO_ICMP && s1 < PFOTHERS_NSTATES &&
81173baed14Scanacar s2 < PFOTHERS_NSTATES) {
81273baed14Scanacar /* XXX ICMP doesn't really have state levels */
81373baed14Scanacar const char *states[] = PFOTHERS_NAMES;
81473baed14Scanacar tbprintf("%s:%s", states[s1], states[s2]);
81573baed14Scanacar } else {
81673baed14Scanacar tbprintf("%u:%u", s1, s2);
81773baed14Scanacar }
81873baed14Scanacar
81973baed14Scanacar if (strlen(tmp_buf) > len) {
82073baed14Scanacar tb_start();
82173baed14Scanacar tbprintf("%u:%u", s1, s2);
82273baed14Scanacar }
82373baed14Scanacar
82473baed14Scanacar print_fld_tb(fld);
82573baed14Scanacar }
82673baed14Scanacar
82773baed14Scanacar int
print_state(struct pfsync_state * s,struct sc_ent * ent)828d93808b7Scanacar print_state(struct pfsync_state * s, struct sc_ent * ent)
82973baed14Scanacar {
830d93808b7Scanacar struct pfsync_state_peer *src, *dst;
83173baed14Scanacar struct protoent *p;
832d93808b7Scanacar u_int64_t sz;
833d25344e8Sclaudio int afto, dir;
83473baed14Scanacar
835d25344e8Sclaudio afto = s->key[PF_SK_STACK].af == s->key[PF_SK_WIRE].af ? 0 : 1;
836d25344e8Sclaudio dir = afto ? PF_OUT : s->direction;
837d25344e8Sclaudio
838d25344e8Sclaudio if (dir == PF_OUT) {
83973baed14Scanacar src = &s->src;
84073baed14Scanacar dst = &s->dst;
84173baed14Scanacar } else {
84273baed14Scanacar src = &s->dst;
84373baed14Scanacar dst = &s->src;
84473baed14Scanacar }
84573baed14Scanacar
84673baed14Scanacar p = getprotobynumber(s->proto);
84773baed14Scanacar
84873baed14Scanacar if (p != NULL)
84973baed14Scanacar print_fld_str(FLD_PROTO, p->p_name);
85073baed14Scanacar else
85173baed14Scanacar print_fld_uint(FLD_PROTO, s->proto);
85273baed14Scanacar
853d25344e8Sclaudio if (dir == PF_OUT) {
854d25344e8Sclaudio print_fld_host2(FLD_SRC,
855d25344e8Sclaudio &s->key[afto ? PF_SK_STACK : PF_SK_WIRE],
856d25344e8Sclaudio &s->key[PF_SK_STACK], 1);
857d25344e8Sclaudio print_fld_host2(FLD_DEST,
858d25344e8Sclaudio &s->key[afto ? PF_SK_STACK : PF_SK_WIRE],
859d25344e8Sclaudio &s->key[afto ? PF_SK_WIRE : PF_SK_STACK], 0);
86073baed14Scanacar } else {
86173baed14Scanacar print_fld_host2(FLD_SRC, &s->key[PF_SK_STACK],
862d25344e8Sclaudio &s->key[PF_SK_WIRE], 0);
86373baed14Scanacar print_fld_host2(FLD_DEST, &s->key[PF_SK_STACK],
864d25344e8Sclaudio &s->key[PF_SK_WIRE], 1);
86573baed14Scanacar }
86673baed14Scanacar
867d25344e8Sclaudio if (dir == PF_OUT)
86873baed14Scanacar print_fld_str(FLD_DIR, "Out");
86973baed14Scanacar else
87073baed14Scanacar print_fld_str(FLD_DIR, "In");
87173baed14Scanacar
87273baed14Scanacar print_fld_state(FLD_STATE, s->proto, src->state, dst->state);
873d20a4fd2Smcbride print_fld_age(FLD_AGE, ntohl(s->creation));
874d20a4fd2Smcbride print_fld_age(FLD_EXP, ntohl(s->expire));
875d93808b7Scanacar
876d93808b7Scanacar sz = COUNTER(s->bytes[0]) + COUNTER(s->bytes[1]);
87773baed14Scanacar
87873baed14Scanacar print_fld_size(FLD_PKTS, COUNTER(s->packets[0]) +
87973baed14Scanacar COUNTER(s->packets[1]));
88073baed14Scanacar print_fld_size(FLD_BYTES, sz);
881d20a4fd2Smcbride print_fld_rate(FLD_SA, (s->creation) ?
8825ddc7cc1Scanacar ((double)sz/(double)ntohl(s->creation)) : -1);
88373baed14Scanacar
8844d6ee8b4Scanacar print_fld_uint(FLD_RULE, ntohl(s->rule));
88573baed14Scanacar if (cachestates && ent != NULL) {
88673baed14Scanacar print_fld_rate(FLD_SI, ent->rate);
88773baed14Scanacar print_fld_rate(FLD_SP, ent->peak);
88873baed14Scanacar }
88973baed14Scanacar
89073baed14Scanacar end_line();
89173baed14Scanacar return 1;
89273baed14Scanacar }
89373baed14Scanacar
89473baed14Scanacar void
print_states(void)89573baed14Scanacar print_states(void)
89673baed14Scanacar {
89773baed14Scanacar int n, count = 0;
89873baed14Scanacar
89973baed14Scanacar for (n = dispstart; n < num_disp; n++) {
90073baed14Scanacar count += print_state(state_buf + state_ord[n],
90173baed14Scanacar state_cache[state_ord[n]]);
90273baed14Scanacar if (maxprint > 0 && count >= maxprint)
90373baed14Scanacar break;
90473baed14Scanacar }
90573baed14Scanacar }
90673baed14Scanacar
90773baed14Scanacar /* rule display */
90873baed14Scanacar
90973baed14Scanacar struct pf_rule *rules = NULL;
91073baed14Scanacar u_int32_t alloc_rules = 0;
91173baed14Scanacar
91273baed14Scanacar int
select_rules(void)91373baed14Scanacar select_rules(void)
91473baed14Scanacar {
91573baed14Scanacar num_disp = num_rules;
91673baed14Scanacar return (0);
91773baed14Scanacar }
91873baed14Scanacar
91973baed14Scanacar
92073baed14Scanacar void
add_rule_alloc(u_int32_t nr)92173baed14Scanacar add_rule_alloc(u_int32_t nr)
92273baed14Scanacar {
92373baed14Scanacar if (nr == 0)
92473baed14Scanacar return;
92573baed14Scanacar
92673baed14Scanacar num_rules += nr;
92773baed14Scanacar
92873baed14Scanacar if (rules == NULL) {
9292daca27aSdoug rules = reallocarray(NULL, num_rules, sizeof(struct pf_rule));
93073baed14Scanacar if (rules == NULL)
93173baed14Scanacar err(1, "malloc");
93273baed14Scanacar alloc_rules = num_rules;
93373baed14Scanacar } else if (num_rules > alloc_rules) {
9342daca27aSdoug rules = reallocarray(rules, num_rules, sizeof(struct pf_rule));
93573baed14Scanacar if (rules == NULL)
93673baed14Scanacar err(1, "realloc");
93773baed14Scanacar alloc_rules = num_rules;
93873baed14Scanacar }
93973baed14Scanacar }
94073baed14Scanacar
94173baed14Scanacar int label_length;
94273baed14Scanacar
943d2364f60Ssashan void
close_pf_trans(u_int32_t ticket)944d2364f60Ssashan close_pf_trans(u_int32_t ticket)
945d2364f60Ssashan {
946d2364f60Ssashan if (ioctl(pf_dev, DIOCXEND, &ticket) == -1)
947d2364f60Ssashan error("DIOCXEND: %s", strerror(errno));
948d2364f60Ssashan }
949d2364f60Ssashan
95073baed14Scanacar int
read_anchor_rules(char * anchor)95173baed14Scanacar read_anchor_rules(char *anchor)
95273baed14Scanacar {
95373baed14Scanacar struct pfioc_rule pr;
95473baed14Scanacar u_int32_t nr, num, off;
955d93808b7Scanacar int len;
95673baed14Scanacar
95773baed14Scanacar if (pf_dev < 0)
95873baed14Scanacar return (-1);
95973baed14Scanacar
96073baed14Scanacar memset(&pr, 0, sizeof(pr));
96173baed14Scanacar strlcpy(pr.anchor, anchor, sizeof(pr.anchor));
962d93808b7Scanacar
9633aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETRULES, &pr) == -1) {
96473baed14Scanacar error("anchor %s: %s", anchor, strerror(errno));
96573baed14Scanacar return (-1);
96673baed14Scanacar }
96773baed14Scanacar
96873baed14Scanacar off = num_rules;
96973baed14Scanacar num = pr.nr;
97073baed14Scanacar add_rule_alloc(num);
97173baed14Scanacar
97273baed14Scanacar for (nr = 0; nr < num; ++nr) {
97373baed14Scanacar pr.nr = nr;
9743aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETRULE, &pr) == -1) {
97573baed14Scanacar error("DIOCGETRULE: %s", strerror(errno));
976d2364f60Ssashan close_pf_trans(pr.ticket);
97773baed14Scanacar return (-1);
97873baed14Scanacar }
97973baed14Scanacar /* XXX overload pr.anchor, to store a pointer to
98073baed14Scanacar * anchor name */
98173baed14Scanacar pr.rule.anchor = (struct pf_anchor *) anchor;
982d93808b7Scanacar len = strlen(pr.rule.label);
98373baed14Scanacar if (len > label_length)
98473baed14Scanacar label_length = len;
98573baed14Scanacar rules[off + nr] = pr.rule;
98673baed14Scanacar }
98773baed14Scanacar
988d2364f60Ssashan close_pf_trans(pr.ticket);
989d2364f60Ssashan
99073baed14Scanacar return (num);
99173baed14Scanacar }
99273baed14Scanacar
99373baed14Scanacar struct anchor_name {
9948f6b3bafSderaadt char name[PATH_MAX];
99573baed14Scanacar struct anchor_name *next;
99673baed14Scanacar u_int32_t ref;
99773baed14Scanacar };
99873baed14Scanacar
99973baed14Scanacar struct anchor_name *anchor_root = NULL;
100073baed14Scanacar struct anchor_name *anchor_end = NULL;
100173baed14Scanacar struct anchor_name *anchor_free = NULL;
100273baed14Scanacar
100373baed14Scanacar struct anchor_name*
alloc_anchor_name(const char * path)100473baed14Scanacar alloc_anchor_name(const char *path)
100573baed14Scanacar {
100673baed14Scanacar struct anchor_name *a;
100773baed14Scanacar
100873baed14Scanacar a = anchor_free;
100973baed14Scanacar if (a == NULL) {
1010cfff592fSderaadt a = malloc(sizeof(struct anchor_name));
101173baed14Scanacar if (a == NULL)
101273baed14Scanacar return (NULL);
101373baed14Scanacar } else
101473baed14Scanacar anchor_free = a->next;
101573baed14Scanacar
101673baed14Scanacar if (anchor_root == NULL)
101773baed14Scanacar anchor_end = a;
101873baed14Scanacar
101973baed14Scanacar a->next = anchor_root;
102073baed14Scanacar anchor_root = a;
102173baed14Scanacar
102273baed14Scanacar a->ref = 0;
102373baed14Scanacar strlcpy(a->name, path, sizeof(a->name));
102473baed14Scanacar return (a);
102573baed14Scanacar }
102673baed14Scanacar
102773baed14Scanacar void
reset_anchor_names(void)102873baed14Scanacar reset_anchor_names(void)
102973baed14Scanacar {
103073baed14Scanacar if (anchor_end == NULL)
103173baed14Scanacar return;
103273baed14Scanacar
103373baed14Scanacar anchor_end->next = anchor_free;
103473baed14Scanacar anchor_free = anchor_root;
103573baed14Scanacar anchor_root = anchor_end = NULL;
103673baed14Scanacar }
103773baed14Scanacar
103873baed14Scanacar struct pfioc_ruleset ruleset;
103973baed14Scanacar char *rs_end = NULL;
104073baed14Scanacar
104173baed14Scanacar int
read_rulesets(const char * path)104273baed14Scanacar read_rulesets(const char *path)
104373baed14Scanacar {
104473baed14Scanacar char *pre;
104573baed14Scanacar struct anchor_name *a;
104673baed14Scanacar u_int32_t nr, ns;
104773baed14Scanacar int len;
104873baed14Scanacar
104973baed14Scanacar if (path == NULL)
105073baed14Scanacar ruleset.path[0] = '\0';
105173baed14Scanacar else if (strlcpy(ruleset.path, path, sizeof(ruleset.path)) >=
105273baed14Scanacar sizeof(ruleset.path))
105373baed14Scanacar return (-1);
105473baed14Scanacar
105573baed14Scanacar /* a persistent storage for anchor names */
105673baed14Scanacar a = alloc_anchor_name(ruleset.path);
105773baed14Scanacar if (a == NULL)
105873baed14Scanacar return (-1);
105973baed14Scanacar
106073baed14Scanacar len = read_anchor_rules(a->name);
106173baed14Scanacar if (len < 0)
106273baed14Scanacar return (-1);
106373baed14Scanacar
106473baed14Scanacar a->ref += len;
106573baed14Scanacar
10663aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETRULESETS, &ruleset) == -1) {
106773baed14Scanacar error("DIOCGETRULESETS: %s", strerror(errno));
106873baed14Scanacar return (-1);
106973baed14Scanacar }
107073baed14Scanacar
107173baed14Scanacar ns = ruleset.nr;
107273baed14Scanacar
107373baed14Scanacar if (rs_end == NULL)
107473baed14Scanacar rs_end = ruleset.path + sizeof(ruleset.path);
107573baed14Scanacar
107673baed14Scanacar /* 'pre' tracks the previous level on the anchor */
107773baed14Scanacar pre = strchr(ruleset.path, 0);
107873baed14Scanacar len = rs_end - pre;
107973baed14Scanacar if (len < 1)
108073baed14Scanacar return (-1);
108173baed14Scanacar --len;
108273baed14Scanacar
108373baed14Scanacar for (nr = 0; nr < ns; ++nr) {
108473baed14Scanacar ruleset.nr = nr;
10853aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETRULESET, &ruleset) == -1) {
108673baed14Scanacar error("DIOCGETRULESET: %s", strerror(errno));
108773baed14Scanacar return (-1);
108873baed14Scanacar }
108973baed14Scanacar *pre = '/';
109073baed14Scanacar if (strlcpy(pre + 1, ruleset.name, len) < len)
109173baed14Scanacar read_rulesets(ruleset.path);
109273baed14Scanacar *pre = '\0';
109373baed14Scanacar }
109473baed14Scanacar
109573baed14Scanacar return (0);
109673baed14Scanacar }
109773baed14Scanacar
109873baed14Scanacar void
compute_anchor_field(void)109973baed14Scanacar compute_anchor_field(void)
110073baed14Scanacar {
110173baed14Scanacar struct anchor_name *a;
110273baed14Scanacar int sum, cnt, mx, nx;
110373baed14Scanacar sum = cnt = mx = 0;
110473baed14Scanacar
110573baed14Scanacar for (a = anchor_root; a != NULL; a = a->next, cnt++) {
110673baed14Scanacar int len;
110773baed14Scanacar if (a->ref == 0)
110873baed14Scanacar continue;
110973baed14Scanacar len = strlen(a->name);
111073baed14Scanacar sum += len;
111173baed14Scanacar if (len > mx)
111273baed14Scanacar mx = len;
111373baed14Scanacar }
111473baed14Scanacar
111573baed14Scanacar nx = sum/cnt;
111673baed14Scanacar if (nx < ANCHOR_FLD_SIZE)
111773baed14Scanacar nx = (mx < ANCHOR_FLD_SIZE) ? mx : ANCHOR_FLD_SIZE;
111873baed14Scanacar
111973baed14Scanacar if (FLD_ANCHOR->max_width != mx ||
112073baed14Scanacar FLD_ANCHOR->norm_width != nx) {
112173baed14Scanacar FLD_ANCHOR->max_width = mx;
112273baed14Scanacar FLD_ANCHOR->norm_width = nx;
112373baed14Scanacar field_setup();
112473baed14Scanacar need_update = 1;
112573baed14Scanacar }
112673baed14Scanacar }
112773baed14Scanacar
112873baed14Scanacar int
read_rules(void)112973baed14Scanacar read_rules(void)
113073baed14Scanacar {
1131d93808b7Scanacar int ret, nw, mw;
113273baed14Scanacar num_rules = 0;
113373baed14Scanacar
113473baed14Scanacar if (pf_dev == -1)
113573baed14Scanacar return (-1);
113673baed14Scanacar
113773baed14Scanacar label_length = MIN_LABEL_SIZE;
113873baed14Scanacar
113973baed14Scanacar reset_anchor_names();
114073baed14Scanacar ret = read_rulesets(NULL);
114173baed14Scanacar compute_anchor_field();
114273baed14Scanacar
114373baed14Scanacar nw = mw = label_length;
114473baed14Scanacar if (nw > 16)
114573baed14Scanacar nw = 16;
114673baed14Scanacar
114773baed14Scanacar if (FLD_LABEL->norm_width != nw ||
114873baed14Scanacar FLD_LABEL->max_width != mw) {
114973baed14Scanacar FLD_LABEL->norm_width = nw;
115073baed14Scanacar FLD_LABEL->max_width = mw;
115173baed14Scanacar field_setup();
115273baed14Scanacar need_update = 1;
115373baed14Scanacar }
115473baed14Scanacar
115573baed14Scanacar num_disp = num_rules;
115673baed14Scanacar return (ret);
115773baed14Scanacar }
115873baed14Scanacar
115973baed14Scanacar void
tb_print_addrw(struct pf_addr_wrap * addr,struct pf_addr * mask,u_int8_t af)116073baed14Scanacar tb_print_addrw(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af)
116173baed14Scanacar {
116273baed14Scanacar switch (addr->type) {
116373baed14Scanacar case PF_ADDR_ADDRMASK:
116473baed14Scanacar tb_print_addr(&addr->v.a.addr, mask, af);
116573baed14Scanacar break;
116673baed14Scanacar case PF_ADDR_NOROUTE:
116773baed14Scanacar tbprintf("noroute");
116873baed14Scanacar break;
116973baed14Scanacar case PF_ADDR_DYNIFTL:
117073baed14Scanacar tbprintf("(%s)", addr->v.ifname);
117173baed14Scanacar break;
117273baed14Scanacar case PF_ADDR_TABLE:
117373baed14Scanacar tbprintf("<%s>", addr->v.tblname);
117473baed14Scanacar break;
117573baed14Scanacar default:
117673baed14Scanacar tbprintf("UNKNOWN");
117773baed14Scanacar break;
117873baed14Scanacar }
117973baed14Scanacar }
118073baed14Scanacar
118173baed14Scanacar void
tb_print_op(u_int8_t op,const char * a1,const char * a2)118273baed14Scanacar tb_print_op(u_int8_t op, const char *a1, const char *a2)
118373baed14Scanacar {
118473baed14Scanacar if (op == PF_OP_IRG)
118573baed14Scanacar tbprintf("%s >< %s ", a1, a2);
118673baed14Scanacar else if (op == PF_OP_XRG)
118773baed14Scanacar tbprintf("%s <> %s ", a1, a2);
118873baed14Scanacar else if (op == PF_OP_RRG)
118973baed14Scanacar tbprintf("%s:%s ", a1, a2);
119073baed14Scanacar else if (op == PF_OP_EQ)
119173baed14Scanacar tbprintf("= %s ", a1);
119273baed14Scanacar else if (op == PF_OP_NE)
119373baed14Scanacar tbprintf("!= %s ", a1);
119473baed14Scanacar else if (op == PF_OP_LT)
119573baed14Scanacar tbprintf("< %s ", a1);
119673baed14Scanacar else if (op == PF_OP_LE)
119773baed14Scanacar tbprintf("<= %s ", a1);
119873baed14Scanacar else if (op == PF_OP_GT)
119973baed14Scanacar tbprintf("> %s ", a1);
120073baed14Scanacar else if (op == PF_OP_GE)
120173baed14Scanacar tbprintf(">= %s ", a1);
120273baed14Scanacar }
120373baed14Scanacar
120473baed14Scanacar void
tb_print_port(u_int8_t op,u_int16_t p1,u_int16_t p2,char * proto)120573baed14Scanacar tb_print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto)
120673baed14Scanacar {
120773baed14Scanacar char a1[6], a2[6];
120873baed14Scanacar struct servent *s = getservbyport(p1, proto);
120973baed14Scanacar
121073baed14Scanacar p1 = ntohs(p1);
121173baed14Scanacar p2 = ntohs(p2);
121273baed14Scanacar snprintf(a1, sizeof(a1), "%u", p1);
121373baed14Scanacar snprintf(a2, sizeof(a2), "%u", p2);
121473baed14Scanacar tbprintf("port ");
121573baed14Scanacar if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE))
121673baed14Scanacar tb_print_op(op, s->s_name, a2);
121773baed14Scanacar else
121873baed14Scanacar tb_print_op(op, a1, a2);
121973baed14Scanacar }
122073baed14Scanacar
122173baed14Scanacar void
tb_print_fromto(struct pf_rule_addr * src,struct pf_rule_addr * dst,u_int8_t af,u_int8_t proto)122273baed14Scanacar tb_print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst,
122373baed14Scanacar u_int8_t af, u_int8_t proto)
122473baed14Scanacar {
122573baed14Scanacar if (
122673baed14Scanacar PF_AZERO(PT_ADDR(src), AF_INET6) &&
122773baed14Scanacar PF_AZERO(PT_ADDR(dst), AF_INET6) &&
122873baed14Scanacar ! PT_NOROUTE(src) && ! PT_NOROUTE(dst) &&
122973baed14Scanacar PF_AZERO(PT_MASK(src), AF_INET6) &&
123073baed14Scanacar PF_AZERO(PT_MASK(dst), AF_INET6) &&
123173baed14Scanacar !src->port_op && !dst->port_op)
123273baed14Scanacar tbprintf("all ");
123373baed14Scanacar else {
123473baed14Scanacar tbprintf("from ");
123573baed14Scanacar if (PT_NOROUTE(src))
123673baed14Scanacar tbprintf("no-route ");
123773baed14Scanacar else if (PF_AZERO(PT_ADDR(src), AF_INET6) &&
123873baed14Scanacar PF_AZERO(PT_MASK(src), AF_INET6))
123973baed14Scanacar tbprintf("any ");
124073baed14Scanacar else {
124173baed14Scanacar if (src->neg)
124273baed14Scanacar tbprintf("! ");
124373baed14Scanacar tb_print_addrw(&src->addr, PT_MASK(src), af);
124473baed14Scanacar tbprintf(" ");
124573baed14Scanacar }
124673baed14Scanacar if (src->port_op)
124773baed14Scanacar tb_print_port(src->port_op, src->port[0],
124873baed14Scanacar src->port[1],
124973baed14Scanacar proto == IPPROTO_TCP ? "tcp" : "udp");
125073baed14Scanacar
125173baed14Scanacar tbprintf("to ");
125273baed14Scanacar if (PT_NOROUTE(dst))
125373baed14Scanacar tbprintf("no-route ");
125473baed14Scanacar else if (PF_AZERO(PT_ADDR(dst), AF_INET6) &&
125573baed14Scanacar PF_AZERO(PT_MASK(dst), AF_INET6))
125673baed14Scanacar tbprintf("any ");
125773baed14Scanacar else {
125873baed14Scanacar if (dst->neg)
125973baed14Scanacar tbprintf("! ");
126073baed14Scanacar tb_print_addrw(&dst->addr, PT_MASK(dst), af);
126173baed14Scanacar tbprintf(" ");
126273baed14Scanacar }
126373baed14Scanacar if (dst->port_op)
126473baed14Scanacar tb_print_port(dst->port_op, dst->port[0],
126573baed14Scanacar dst->port[1],
126673baed14Scanacar proto == IPPROTO_TCP ? "tcp" : "udp");
126773baed14Scanacar }
126873baed14Scanacar }
126973baed14Scanacar
127073baed14Scanacar void
tb_print_ugid(u_int8_t op,id_t i1,id_t i2,const char * t)1271b4de0548Smillert tb_print_ugid(u_int8_t op, id_t i1, id_t i2, const char *t)
127273baed14Scanacar {
127373baed14Scanacar char a1[11], a2[11];
127473baed14Scanacar
1275b4de0548Smillert snprintf(a1, sizeof(a1), "%u", i1);
1276b4de0548Smillert snprintf(a2, sizeof(a2), "%u", i2);
127773baed14Scanacar
127873baed14Scanacar tbprintf("%s ", t);
1279b4de0548Smillert if (i1 == -1 && (op == PF_OP_EQ || op == PF_OP_NE))
128073baed14Scanacar tb_print_op(op, "unknown", a2);
128173baed14Scanacar else
128273baed14Scanacar tb_print_op(op, a1, a2);
128373baed14Scanacar }
128473baed14Scanacar
128573baed14Scanacar void
tb_print_flags(u_int8_t f)128673baed14Scanacar tb_print_flags(u_int8_t f)
128773baed14Scanacar {
128873baed14Scanacar const char *tcpflags = "FSRPAUEW";
128973baed14Scanacar int i;
129073baed14Scanacar
129173baed14Scanacar for (i = 0; tcpflags[i]; ++i)
129273baed14Scanacar if (f & (1 << i))
129373baed14Scanacar tbprintf("%c", tcpflags[i]);
129473baed14Scanacar }
129573baed14Scanacar
129673baed14Scanacar void
print_rule(struct pf_rule * pr)129773baed14Scanacar print_rule(struct pf_rule *pr)
129873baed14Scanacar {
1299af821ee0Shenning static const char *actiontypes[] = { "Pass", "Block", "Scrub",
1300af821ee0Shenning "no Scrub", "Nat", "no Nat", "Binat", "no Binat", "Rdr",
1301af821ee0Shenning "no Rdr", "SynProxy Block", "Defer", "Match" };
130273baed14Scanacar int numact = sizeof(actiontypes) / sizeof(char *);
130373baed14Scanacar
130473baed14Scanacar static const char *routetypes[] = { "", "fastroute", "route-to",
130573baed14Scanacar "dup-to", "reply-to" };
130673baed14Scanacar
130773baed14Scanacar int numroute = sizeof(routetypes) / sizeof(char *);
130873baed14Scanacar
130973baed14Scanacar if (pr == NULL) return;
131073baed14Scanacar
131173baed14Scanacar print_fld_str(FLD_LABEL, pr->label);
131273baed14Scanacar print_fld_size(FLD_STATS, pr->states_tot);
131373baed14Scanacar
131473baed14Scanacar print_fld_size(FLD_PKTS, pr->packets[0] + pr->packets[1]);
131573baed14Scanacar print_fld_size(FLD_BYTES, pr->bytes[0] + pr->bytes[1]);
1316d93808b7Scanacar
131773baed14Scanacar print_fld_uint(FLD_RULE, pr->nr);
13187c6304b1Ssthen if (pr->direction == PF_OUT)
13197c6304b1Ssthen print_fld_str(FLD_DIR, "Out");
13207c6304b1Ssthen else if (pr->direction == PF_IN)
13217c6304b1Ssthen print_fld_str(FLD_DIR, "In");
13227c6304b1Ssthen else
13237c6304b1Ssthen print_fld_str(FLD_DIR, "Any");
13247c6304b1Ssthen
132573baed14Scanacar if (pr->quick)
132673baed14Scanacar print_fld_str(FLD_QUICK, "Quick");
132773baed14Scanacar
132873baed14Scanacar if (pr->keep_state == PF_STATE_NORMAL)
132973baed14Scanacar print_fld_str(FLD_KST, "Keep");
133073baed14Scanacar else if (pr->keep_state == PF_STATE_MODULATE)
133173baed14Scanacar print_fld_str(FLD_KST, "Mod");
13322b0241cfSjsg else if (pr->keep_state == PF_STATE_SYNPROXY)
133373baed14Scanacar print_fld_str(FLD_KST, "Syn");
133473baed14Scanacar if (pr->log == 1)
133573baed14Scanacar print_fld_str(FLD_LOG, "Log");
133673baed14Scanacar else if (pr->log == 2)
133773baed14Scanacar print_fld_str(FLD_LOG, "All");
133873baed14Scanacar
1339d693a71aScanacar if (pr->action >= numact)
134073baed14Scanacar print_fld_uint(FLD_ACTION, pr->action);
134173baed14Scanacar else print_fld_str(FLD_ACTION, actiontypes[pr->action]);
1342d693a71aScanacar
134373baed14Scanacar if (pr->proto) {
134473baed14Scanacar struct protoent *p = getprotobynumber(pr->proto);
134573baed14Scanacar
134673baed14Scanacar if (p != NULL)
134773baed14Scanacar print_fld_str(FLD_PROTO, p->p_name);
134873baed14Scanacar else
134973baed14Scanacar print_fld_uint(FLD_PROTO, pr->proto);
135073baed14Scanacar }
135173baed14Scanacar
135273baed14Scanacar if (pr->ifname[0]) {
135373baed14Scanacar tb_start();
135473baed14Scanacar if (pr->ifnot)
135573baed14Scanacar tbprintf("!");
135673baed14Scanacar tbprintf("%s", pr->ifname);
135773baed14Scanacar print_fld_tb(FLD_IF);
135873baed14Scanacar }
135973baed14Scanacar if (pr->max_states)
136073baed14Scanacar print_fld_uint(FLD_STMAX, pr->max_states);
1361d93808b7Scanacar
136273baed14Scanacar /* print info field */
136373baed14Scanacar
136473baed14Scanacar tb_start();
136573baed14Scanacar
136673baed14Scanacar if (pr->action == PF_DROP) {
136773baed14Scanacar if (pr->rule_flag & PFRULE_RETURNRST)
136873baed14Scanacar tbprintf("return-rst ");
136973baed14Scanacar #ifdef PFRULE_RETURN
137073baed14Scanacar else if (pr->rule_flag & PFRULE_RETURN)
137173baed14Scanacar tbprintf("return ");
137273baed14Scanacar #endif
137373baed14Scanacar #ifdef PFRULE_RETURNICMP
137473baed14Scanacar else if (pr->rule_flag & PFRULE_RETURNICMP)
137573baed14Scanacar tbprintf("return-icmp ");
137673baed14Scanacar #endif
137773baed14Scanacar else
137873baed14Scanacar tbprintf("drop ");
137973baed14Scanacar }
138073baed14Scanacar
138173baed14Scanacar if (pr->rt > 0 && pr->rt < numroute) {
138273baed14Scanacar tbprintf("%s ", routetypes[pr->rt]);
138373baed14Scanacar }
1384d93808b7Scanacar
138573baed14Scanacar if (pr->af) {
138673baed14Scanacar if (pr->af == AF_INET)
138773baed14Scanacar tbprintf("inet ");
138873baed14Scanacar else
138973baed14Scanacar tbprintf("inet6 ");
139073baed14Scanacar }
139173baed14Scanacar
139273baed14Scanacar tb_print_fromto(&pr->src, &pr->dst, pr->af, pr->proto);
1393d93808b7Scanacar
139473baed14Scanacar if (pr->uid.op)
139573baed14Scanacar tb_print_ugid(pr->uid.op, pr->uid.uid[0], pr->uid.uid[1],
1396b4de0548Smillert "user");
139773baed14Scanacar if (pr->gid.op)
139873baed14Scanacar tb_print_ugid(pr->gid.op, pr->gid.gid[0], pr->gid.gid[1],
1399b4de0548Smillert "group");
140073baed14Scanacar
140126f2f421Smcbride if (pr->action == PF_PASS &&
140226f2f421Smcbride (pr->proto == 0 || pr->proto == IPPROTO_TCP) &&
140326f2f421Smcbride (pr->flags != TH_SYN || pr->flagset != (TH_SYN | TH_ACK) )) {
140473baed14Scanacar tbprintf("flags ");
140526f2f421Smcbride if (pr->flags || pr->flagset) {
140673baed14Scanacar tb_print_flags(pr->flags);
140773baed14Scanacar tbprintf("/");
140873baed14Scanacar tb_print_flags(pr->flagset);
140926f2f421Smcbride } else
141026f2f421Smcbride tbprintf("any ");
141173baed14Scanacar }
141273baed14Scanacar
141373baed14Scanacar tbprintf(" ");
141473baed14Scanacar
141573baed14Scanacar if (pr->tos)
141673baed14Scanacar tbprintf("tos 0x%2.2x ", pr->tos);
141773baed14Scanacar #ifdef PFRULE_FRAGMENT
141873baed14Scanacar if (pr->rule_flag & PFRULE_FRAGMENT)
141973baed14Scanacar tbprintf("fragment ");
142073baed14Scanacar #endif
142173baed14Scanacar #ifdef PFRULE_NODF
142273baed14Scanacar if (pr->rule_flag & PFRULE_NODF)
142373baed14Scanacar tbprintf("no-df ");
142473baed14Scanacar #endif
142573baed14Scanacar #ifdef PFRULE_RANDOMID
142673baed14Scanacar if (pr->rule_flag & PFRULE_RANDOMID)
142773baed14Scanacar tbprintf("random-id ");
142873baed14Scanacar #endif
142973baed14Scanacar if (pr->min_ttl)
143073baed14Scanacar tbprintf("min-ttl %d ", pr->min_ttl);
143173baed14Scanacar if (pr->max_mss)
143273baed14Scanacar tbprintf("max-mss %d ", pr->max_mss);
143373baed14Scanacar if (pr->allow_opts)
143473baed14Scanacar tbprintf("allow-opts ");
143573baed14Scanacar
143660e2494dShenning /* XXX more missing */
143773baed14Scanacar
143873baed14Scanacar if (pr->qname[0] && pr->pqname[0])
143973baed14Scanacar tbprintf("queue(%s, %s) ", pr->qname, pr->pqname);
144073baed14Scanacar else if (pr->qname[0])
144173baed14Scanacar tbprintf("queue %s ", pr->qname);
1442d93808b7Scanacar
144373baed14Scanacar if (pr->tagname[0])
144473baed14Scanacar tbprintf("tag %s ", pr->tagname);
144573baed14Scanacar if (pr->match_tagname[0]) {
144673baed14Scanacar if (pr->match_tag_not)
144773baed14Scanacar tbprintf("! ");
144873baed14Scanacar tbprintf("tagged %s ", pr->match_tagname);
144973baed14Scanacar }
1450d93808b7Scanacar
145173baed14Scanacar print_fld_tb(FLD_RINFO);
145273baed14Scanacar
145373baed14Scanacar /* XXX anchor field overloaded with anchor name */
145473baed14Scanacar print_fld_str(FLD_ANCHOR, (char *)pr->anchor);
145573baed14Scanacar tb_end();
145673baed14Scanacar
145773baed14Scanacar end_line();
145873baed14Scanacar }
145973baed14Scanacar
146073baed14Scanacar void
print_rules(void)146173baed14Scanacar print_rules(void)
146273baed14Scanacar {
146373baed14Scanacar u_int32_t n, count = 0;
146473baed14Scanacar
146573baed14Scanacar for (n = dispstart; n < num_rules; n++) {
146673baed14Scanacar print_rule(rules + n);
146773baed14Scanacar count ++;
146873baed14Scanacar if (maxprint > 0 && count >= maxprint)
146973baed14Scanacar break;
147073baed14Scanacar }
147173baed14Scanacar }
147273baed14Scanacar
147373baed14Scanacar /* queue display */
1474aa14b181Shenning struct pfctl_queue_node *
pfctl_find_queue_node(const char * qname,const char * ifname)1475aa14b181Shenning pfctl_find_queue_node(const char *qname, const char *ifname)
1476aa14b181Shenning {
1477aa14b181Shenning struct pfctl_queue_node *node;
1478aa14b181Shenning
1479aa14b181Shenning TAILQ_FOREACH(node, &qnodes, entries)
1480aa14b181Shenning if (!strcmp(node->qs.qname, qname)
1481aa14b181Shenning && !(strcmp(node->qs.ifname, ifname)))
1482aa14b181Shenning return (node);
1483aa14b181Shenning return (NULL);
1484aa14b181Shenning }
1485aa14b181Shenning
1486aa14b181Shenning void
pfctl_insert_queue_node(const struct pf_queuespec qs,const struct queue_stats qstats)1487aa14b181Shenning pfctl_insert_queue_node(const struct pf_queuespec qs,
1488aa14b181Shenning const struct queue_stats qstats)
1489aa14b181Shenning {
1490aa14b181Shenning struct pfctl_queue_node *node, *parent;
1491aa14b181Shenning
1492aa14b181Shenning node = calloc(1, sizeof(struct pfctl_queue_node));
1493aa14b181Shenning if (node == NULL)
1494aa14b181Shenning err(1, "pfctl_insert_queue_node: calloc");
1495aa14b181Shenning memcpy(&node->qs, &qs, sizeof(qs));
1496aa14b181Shenning memcpy(&node->qstats, &qstats, sizeof(qstats));
1497aa14b181Shenning
1498aa14b181Shenning if (node->qs.parent[0]) {
1499aa14b181Shenning parent = pfctl_find_queue_node(node->qs.parent,
1500aa14b181Shenning node->qs.ifname);
1501aa14b181Shenning if (parent)
1502aa14b181Shenning node->depth = parent->depth + 1;
1503aa14b181Shenning }
1504aa14b181Shenning
1505aa14b181Shenning TAILQ_INSERT_TAIL(&qnodes, node, entries);
1506aa14b181Shenning }
1507aa14b181Shenning
150873baed14Scanacar int
pfctl_update_qstats(void)1509aa14b181Shenning pfctl_update_qstats(void)
1510aa14b181Shenning {
1511aa14b181Shenning struct pfctl_queue_node *node;
1512aa14b181Shenning struct pfioc_queue pq;
1513aa14b181Shenning struct pfioc_qstats pqs;
1514aa14b181Shenning u_int32_t mnr, nr;
1515aa14b181Shenning struct queue_stats qstats;
1516aa14b181Shenning static u_int32_t last_ticket;
1517aa14b181Shenning
1518aa14b181Shenning memset(&pq, 0, sizeof(pq));
1519aa14b181Shenning memset(&pqs, 0, sizeof(pqs));
1520aa14b181Shenning memset(&qstats, 0, sizeof(qstats));
1521aa14b181Shenning
1522aa14b181Shenning if (pf_dev < 0)
1523aa14b181Shenning return (-1);
1524aa14b181Shenning
15253aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETQUEUES, &pq) == -1) {
1526aa14b181Shenning error("DIOCGETQUEUES: %s", strerror(errno));
1527aa14b181Shenning return (-1);
1528aa14b181Shenning }
1529aa14b181Shenning
1530aa14b181Shenning /* if a new set is found, start over */
1531aa14b181Shenning if (pq.ticket != last_ticket)
1532635c567dSpelikan while ((node = TAILQ_FIRST(&qnodes)) != NULL) {
1533aa14b181Shenning TAILQ_REMOVE(&qnodes, node, entries);
1534635c567dSpelikan free(node);
1535635c567dSpelikan }
1536aa14b181Shenning last_ticket = pq.ticket;
1537aa14b181Shenning
1538aa14b181Shenning num_queues = mnr = pq.nr;
1539aa14b181Shenning for (nr = 0; nr < mnr; ++nr) {
1540aa14b181Shenning pqs.nr = nr;
1541aa14b181Shenning pqs.ticket = pq.ticket;
1542aa14b181Shenning pqs.buf = &qstats.data;
1543aa14b181Shenning pqs.nbytes = sizeof(qstats.data);
15443aaa63ebSderaadt if (ioctl(pf_dev, DIOCGETQSTATS, &pqs) == -1) {
1545aa14b181Shenning error("DIOCGETQSTATS: %s", strerror(errno));
1546aa14b181Shenning return (-1);
1547aa14b181Shenning }
1548aa14b181Shenning qstats.valid = 1;
1549aa14b181Shenning gettimeofday(&qstats.timestamp, NULL);
1550aa14b181Shenning if ((node = pfctl_find_queue_node(pqs.queue.qname,
1551aa14b181Shenning pqs.queue.ifname)) != NULL) {
1552aa14b181Shenning memcpy(&node->qstats_last, &node->qstats,
1553aa14b181Shenning sizeof(struct queue_stats));
1554aa14b181Shenning memcpy(&node->qstats, &qstats,
1555aa14b181Shenning sizeof(struct queue_stats));
1556aa14b181Shenning } else {
1557aa14b181Shenning pfctl_insert_queue_node(pqs.queue, qstats);
1558aa14b181Shenning }
1559aa14b181Shenning }
1560aa14b181Shenning return (0);
1561aa14b181Shenning }
1562aa14b181Shenning
1563aa14b181Shenning int
select_queues(void)156473baed14Scanacar select_queues(void)
156573baed14Scanacar {
15664e976734Shenning num_disp = num_queues;
156773baed14Scanacar return (0);
156873baed14Scanacar }
156973baed14Scanacar
157073baed14Scanacar int
read_queues(void)157173baed14Scanacar read_queues(void)
157273baed14Scanacar {
15734e976734Shenning num_disp = num_queues = 0;
1574aa14b181Shenning
1575aa14b181Shenning if (pfctl_update_qstats() < 0)
157673baed14Scanacar return (-1);
15774e976734Shenning num_disp = num_queues;
157873baed14Scanacar
157973baed14Scanacar return(0);
158073baed14Scanacar }
158173baed14Scanacar
158273baed14Scanacar double
calc_interval(struct timeval * cur_time,struct timeval * last_time)158373baed14Scanacar calc_interval(struct timeval *cur_time, struct timeval *last_time)
158473baed14Scanacar {
158573baed14Scanacar double sec;
158673baed14Scanacar
158773baed14Scanacar sec = (double)(cur_time->tv_sec - last_time->tv_sec) +
158873baed14Scanacar (double)(cur_time->tv_usec - last_time->tv_usec) / 1000000;
158973baed14Scanacar
159073baed14Scanacar return (sec);
159173baed14Scanacar }
159273baed14Scanacar
159373baed14Scanacar double
calc_rate(u_int64_t new_bytes,u_int64_t last_bytes,double interval)159473baed14Scanacar calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval)
159573baed14Scanacar {
159673baed14Scanacar double rate;
159773baed14Scanacar
159873baed14Scanacar rate = (double)(new_bytes - last_bytes) / interval;
159973baed14Scanacar return (rate);
160073baed14Scanacar }
160173baed14Scanacar
160273baed14Scanacar double
calc_pps(u_int64_t new_pkts,u_int64_t last_pkts,double interval)160373baed14Scanacar calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval)
160473baed14Scanacar {
160573baed14Scanacar double pps;
160673baed14Scanacar
160773baed14Scanacar pps = (double)(new_pkts - last_pkts) / interval;
160873baed14Scanacar return (pps);
160973baed14Scanacar }
161073baed14Scanacar
161173baed14Scanacar void
print_queue_node(struct pfctl_queue_node * node)1612aa14b181Shenning print_queue_node(struct pfctl_queue_node *node)
1613aa14b181Shenning {
1614ab6b4157Smikeb u_int rate, rtmp;
1615aa14b181Shenning int i;
1616aa14b181Shenning double interval, pps, bps;
1617aa14b181Shenning static const char unit[] = " KMG";
1618aa14b181Shenning
1619aa14b181Shenning tb_start();
1620aa14b181Shenning for (i = 0; i < node->depth; i++)
1621aa14b181Shenning tbprintf(" ");
1622aa14b181Shenning tbprintf("%s", node->qs.qname);
16230b4f1cf4Ssthen if (i == 0 && node->qs.ifname[0])
16240b4f1cf4Ssthen tbprintf(" on %s ", node->qs.ifname);
1625aa14b181Shenning print_fld_tb(FLD_QUEUE);
1626aa14b181Shenning
1627aa14b181Shenning // XXX: missing min, max, burst
1628aa14b181Shenning tb_start();
1629aa14b181Shenning rate = node->qs.linkshare.m2.absolute;
1630ab6b4157Smikeb for (i = 0; rate > 9999 && i <= 3; i++) {
1631ab6b4157Smikeb rtmp = rate / 1000;
1632ab6b4157Smikeb if (rtmp <= 9999)
1633ab6b4157Smikeb rtmp += (rate % 1000) / 500;
1634ab6b4157Smikeb rate = rtmp;
1635ab6b4157Smikeb }
163690944f0fSmikeb if (rate == 0 && (node->qs.flags & PFQS_FLOWQUEUE)) {
163790944f0fSmikeb /*
163890944f0fSmikeb * XXX We're abusing the fact that 'flows' in
163990944f0fSmikeb * the fqcodel_stats structure is at the same
164090944f0fSmikeb * spot as the 'period' in hfsc_class_stats.
164190944f0fSmikeb */
164290944f0fSmikeb tbprintf("%u", node->qstats.data.period);
164390944f0fSmikeb } else
1644aa14b181Shenning tbprintf("%u%c", rate, unit[i]);
1645aa14b181Shenning print_fld_tb(FLD_BANDW);
1646aa14b181Shenning
16476cb74e26Smikeb print_fld_str(FLD_SCHED, node->qs.flags & PFQS_FLOWQUEUE ?
16486cb74e26Smikeb "flow" : "fifo");
16496cb74e26Smikeb
1650aa14b181Shenning if (node->qstats.valid && node->qstats_last.valid)
1651aa14b181Shenning interval = calc_interval(&node->qstats.timestamp,
1652aa14b181Shenning &node->qstats_last.timestamp);
1653aa14b181Shenning else
1654aa14b181Shenning interval = 0;
1655aa14b181Shenning
1656aa14b181Shenning print_fld_size(FLD_PKTS, node->qstats.data.xmit_cnt.packets);
1657aa14b181Shenning print_fld_size(FLD_BYTES, node->qstats.data.xmit_cnt.bytes);
1658aa14b181Shenning print_fld_size(FLD_DROPP, node->qstats.data.drop_cnt.packets);
1659aa14b181Shenning print_fld_size(FLD_DROPB, node->qstats.data.drop_cnt.bytes);
1660aa14b181Shenning print_fld_size(FLD_QLEN, node->qstats.data.qlength);
1661aa14b181Shenning
1662aa14b181Shenning if (interval > 0) {
1663aa14b181Shenning pps = calc_pps(node->qstats.data.xmit_cnt.packets,
1664aa14b181Shenning node->qstats_last.data.xmit_cnt.packets, interval);
1665aa14b181Shenning bps = calc_rate(node->qstats.data.xmit_cnt.bytes,
1666aa14b181Shenning node->qstats_last.data.xmit_cnt.bytes, interval);
1667aa14b181Shenning
1668aa14b181Shenning tb_start();
1669aa14b181Shenning if (pps > 0 && pps < 1)
1670aa14b181Shenning tbprintf("%-3.1lf", pps);
1671aa14b181Shenning else
1672aa14b181Shenning tbprintf("%u", (unsigned int)pps);
1673aa14b181Shenning
1674aa14b181Shenning print_fld_tb(FLD_PKTSPS);
1675aa14b181Shenning print_fld_bw(FLD_BYTESPS, bps);
1676aa14b181Shenning }
1677aa14b181Shenning }
1678aa14b181Shenning
1679aa14b181Shenning void
print_queues(void)168073baed14Scanacar print_queues(void)
168173baed14Scanacar {
1682aa14b181Shenning uint32_t n, count, start;
1683aa14b181Shenning struct pfctl_queue_node *node;
168473baed14Scanacar
1685aa14b181Shenning n = count = 0;
1686aa14b181Shenning start = dispstart;
168773baed14Scanacar
1688aa14b181Shenning TAILQ_FOREACH(node, &qnodes, entries) {
1689aa14b181Shenning if (n < start) {
1690aa14b181Shenning n++;
1691aa14b181Shenning continue;
1692aa14b181Shenning }
1693aa14b181Shenning print_queue_node(node);
1694aa14b181Shenning end_line();
1695aa14b181Shenning count++;
1696aa14b181Shenning if (maxprint > 0 && count >= maxprint)
1697aa14b181Shenning return;
1698aa14b181Shenning }
169973baed14Scanacar }
170073baed14Scanacar
170173baed14Scanacar /* main program functions */
170273baed14Scanacar
170373baed14Scanacar void
update_cache(void)1704035d703dScanacar update_cache(void)
170573baed14Scanacar {
170673baed14Scanacar static int pstate = -1;
170773baed14Scanacar if (pstate == cachestates)
170873baed14Scanacar return;
170973baed14Scanacar
171073baed14Scanacar pstate = cachestates;
171173baed14Scanacar if (cachestates) {
171273baed14Scanacar show_field(FLD_SI);
171373baed14Scanacar show_field(FLD_SP);
171473baed14Scanacar gotsig_alarm = 1;
171573baed14Scanacar } else {
171673baed14Scanacar hide_field(FLD_SI);
171773baed14Scanacar hide_field(FLD_SP);
171873baed14Scanacar need_update = 1;
171973baed14Scanacar }
172073baed14Scanacar field_setup();
172173baed14Scanacar }
172273baed14Scanacar
1723035d703dScanacar int
initpftop(void)172473baed14Scanacar initpftop(void)
172573baed14Scanacar {
172673baed14Scanacar struct pf_status status;
172773baed14Scanacar field_view *v;
172873baed14Scanacar int cachesize = DEFAULT_CACHE_SIZE;
172973baed14Scanacar
173073baed14Scanacar v = views;
173173baed14Scanacar while(v->name != NULL)
173273baed14Scanacar add_view(v++);
173373baed14Scanacar
173473baed14Scanacar pf_dev = open("/dev/pf", O_RDONLY);
173573baed14Scanacar if (pf_dev == -1) {
173673baed14Scanacar alloc_buf(0);
17373aaa63ebSderaadt } else if (ioctl(pf_dev, DIOCGETSTATUS, &status) == -1) {
173873baed14Scanacar warn("DIOCGETSTATUS");
173973baed14Scanacar alloc_buf(0);
174073baed14Scanacar } else
174173baed14Scanacar alloc_buf(status.states);
174273baed14Scanacar
174373baed14Scanacar /* initialize cache with given size */
174473baed14Scanacar if (cache_init(cachesize))
174573baed14Scanacar warnx("Failed to initialize cache.");
174673baed14Scanacar else if (interactive && cachesize > 0)
174773baed14Scanacar cachestates = 1;
174873baed14Scanacar
174973baed14Scanacar update_cache();
175073baed14Scanacar
175173baed14Scanacar show_field(FLD_STMAX);
175273baed14Scanacar show_field(FLD_ANCHOR);
1753035d703dScanacar
1754035d703dScanacar return (1);
175573baed14Scanacar }
1756