1 /* $OpenBSD: pftop.c,v 1.45 2019/10/17 21:54:29 millert 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 size_t state_buf_len = 0; 111 size_t *state_ord = NULL; 112 size_t num_states = 0; 113 size_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, order_list 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[* (size_t *) s1].bytes[0]) + 315 COUNTER(state_buf[* (size_t *) s1].bytes[1]); 316 u_int64_t b2 = COUNTER(state_buf[* (size_t *) s2].bytes[0]) + 317 COUNTER(state_buf[* (size_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[* (size_t *) s1].packets[0]) + 329 COUNTER(state_buf[* (size_t *) s1].packets[1]); 330 u_int64_t p2 = COUNTER(state_buf[* (size_t *) s2].packets[0]) + 331 COUNTER(state_buf[* (size_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[* (size_t *) s2].creation) > 343 ntohl(state_buf[* (size_t *) s1].creation)) 344 return sortdir; 345 if (ntohl(state_buf[* (size_t *) s2].creation) < 346 ntohl(state_buf[* (size_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[* (size_t *) s2].expire) > 355 ntohl(state_buf[* (size_t *) s1].expire)) 356 return sortdir; 357 if (ntohl(state_buf[* (size_t *) s2].expire) < 358 ntohl(state_buf[* (size_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 + (* (size_t *) p1); 573 struct pfsync_state *s2 = state_buf + (* (size_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 + (* (size_t *) p1); 581 struct pfsync_state *s2 = state_buf + (* (size_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 + (* (size_t *) p1); 589 struct pfsync_state *s2 = state_buf + (* (size_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 + (* (size_t *) p1); 597 struct pfsync_state *s2 = state_buf + (* (size_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(size_t), ordering->func); 621 } 622 623 /* state management functions */ 624 625 void 626 alloc_buf(size_t ns) 627 { 628 size_t 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(size_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 size_t n; 661 662 if (pf_dev == -1) 663 return -1; 664 665 for (;;) { 666 size_t sbytes = state_buf_len * sizeof(struct pfsync_state); 667 668 ps.ps_len = sbytes; 669 ps.ps_states = state_buf; 670 671 if (ioctl(pf_dev, DIOCGETSTATES, &ps) == -1) { 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) 698 { 699 int i = 31, j = 0, b = 0; 700 u_int32_t tmp; 701 702 while (j < 4 && m->addr32[j] == 0xffffffff) { 703 b += 32; 704 j++; 705 } 706 if (j < 4) { 707 tmp = ntohl(m->addr32[j]); 708 for (i = 31; tmp & (1 << i); --i) 709 b++; 710 } 711 return (b); 712 } 713 714 /* display functions */ 715 716 void 717 tb_print_addr(struct pf_addr * addr, struct pf_addr * mask, int af) 718 { 719 switch (af) { 720 case AF_INET: { 721 tbprintf("%s", inetname(addr->v4)); 722 break; 723 } 724 case AF_INET6: { 725 tbprintf("%s", inet6name(&addr->v6)); 726 break; 727 } 728 } 729 730 if (mask != NULL) { 731 if (!PF_AZERO(mask, af)) 732 tbprintf("/%u", unmask(mask)); 733 } 734 } 735 736 void 737 print_fld_host2(field_def *fld, struct pfsync_state_key *ks, 738 struct pfsync_state_key *kn, int idx) 739 { 740 struct pf_addr *as = &ks->addr[idx]; 741 struct pf_addr *an = &kn->addr[idx]; 742 743 u_int16_t ps = ntohs(ks->port[idx]); 744 u_int16_t pn = ntohs(kn->port[idx]); 745 746 int asf = ks->af; 747 int anf = kn->af; 748 749 if (fld == NULL) 750 return; 751 752 if (fld->width < 3) { 753 print_fld_str(fld, "*"); 754 return; 755 } 756 757 tb_start(); 758 tb_print_addr(as, NULL, asf); 759 760 if (asf == AF_INET) 761 tbprintf(":%u", ps); 762 else 763 tbprintf("[%u]", ps); 764 765 print_fld_tb(fld); 766 767 if (asf != anf || PF_ANEQ(as, an, asf) || ps != pn) { 768 tb_start(); 769 tb_print_addr(an, NULL, anf); 770 771 if (anf == AF_INET) 772 tbprintf(":%u", pn); 773 else 774 tbprintf("[%u]", pn); 775 print_fld_tb(FLD_GW); 776 } 777 778 } 779 780 void 781 print_fld_state(field_def *fld, unsigned int proto, 782 unsigned int s1, unsigned int s2) 783 { 784 int len; 785 786 if (fld == NULL) 787 return; 788 789 len = fld->width; 790 if (len < 1) 791 return; 792 793 tb_start(); 794 795 if (proto == IPPROTO_TCP) { 796 if (s1 <= TCPS_TIME_WAIT && s2 <= TCPS_TIME_WAIT) 797 tbprintf("%s:%s", tcpstates[s1], tcpstates[s2]); 798 #ifdef PF_TCPS_PROXY_SRC 799 else if (s1 == PF_TCPS_PROXY_SRC || 800 s2 == PF_TCPS_PROXY_SRC) 801 tbprintf("PROXY:SRC\n"); 802 else if (s1 == PF_TCPS_PROXY_DST || 803 s2 == PF_TCPS_PROXY_DST) 804 tbprintf("PROXY:DST\n"); 805 #endif 806 else 807 tbprintf("<BAD STATE LEVELS>"); 808 } else if (proto == IPPROTO_UDP && s1 < PFUDPS_NSTATES && 809 s2 < PFUDPS_NSTATES) { 810 const char *states[] = PFUDPS_NAMES; 811 tbprintf("%s:%s", states[s1], states[s2]); 812 } else if (proto != IPPROTO_ICMP && s1 < PFOTHERS_NSTATES && 813 s2 < PFOTHERS_NSTATES) { 814 /* XXX ICMP doesn't really have state levels */ 815 const char *states[] = PFOTHERS_NAMES; 816 tbprintf("%s:%s", states[s1], states[s2]); 817 } else { 818 tbprintf("%u:%u", s1, s2); 819 } 820 821 if (strlen(tmp_buf) > len) { 822 tb_start(); 823 tbprintf("%u:%u", s1, s2); 824 } 825 826 print_fld_tb(fld); 827 } 828 829 int 830 print_state(struct pfsync_state * s, struct sc_ent * ent) 831 { 832 struct pfsync_state_peer *src, *dst; 833 struct protoent *p; 834 u_int64_t sz; 835 int afto, dir; 836 837 afto = s->key[PF_SK_STACK].af == s->key[PF_SK_WIRE].af ? 0 : 1; 838 dir = afto ? PF_OUT : s->direction; 839 840 if (dir == PF_OUT) { 841 src = &s->src; 842 dst = &s->dst; 843 } else { 844 src = &s->dst; 845 dst = &s->src; 846 } 847 848 p = getprotobynumber(s->proto); 849 850 if (p != NULL) 851 print_fld_str(FLD_PROTO, p->p_name); 852 else 853 print_fld_uint(FLD_PROTO, s->proto); 854 855 if (dir == PF_OUT) { 856 print_fld_host2(FLD_SRC, 857 &s->key[afto ? PF_SK_STACK : PF_SK_WIRE], 858 &s->key[PF_SK_STACK], 1); 859 print_fld_host2(FLD_DEST, 860 &s->key[afto ? PF_SK_STACK : PF_SK_WIRE], 861 &s->key[afto ? PF_SK_WIRE : PF_SK_STACK], 0); 862 } else { 863 print_fld_host2(FLD_SRC, &s->key[PF_SK_STACK], 864 &s->key[PF_SK_WIRE], 0); 865 print_fld_host2(FLD_DEST, &s->key[PF_SK_STACK], 866 &s->key[PF_SK_WIRE], 1); 867 } 868 869 if (dir == PF_OUT) 870 print_fld_str(FLD_DIR, "Out"); 871 else 872 print_fld_str(FLD_DIR, "In"); 873 874 print_fld_state(FLD_STATE, s->proto, src->state, dst->state); 875 print_fld_age(FLD_AGE, ntohl(s->creation)); 876 print_fld_age(FLD_EXP, ntohl(s->expire)); 877 878 sz = COUNTER(s->bytes[0]) + COUNTER(s->bytes[1]); 879 880 print_fld_size(FLD_PKTS, COUNTER(s->packets[0]) + 881 COUNTER(s->packets[1])); 882 print_fld_size(FLD_BYTES, sz); 883 print_fld_rate(FLD_SA, (s->creation) ? 884 ((double)sz/(double)ntohl(s->creation)) : -1); 885 886 print_fld_uint(FLD_RULE, ntohl(s->rule)); 887 if (cachestates && ent != NULL) { 888 print_fld_rate(FLD_SI, ent->rate); 889 print_fld_rate(FLD_SP, ent->peak); 890 } 891 892 end_line(); 893 return 1; 894 } 895 896 void 897 print_states(void) 898 { 899 int n, count = 0; 900 901 for (n = dispstart; n < num_disp; n++) { 902 count += print_state(state_buf + state_ord[n], 903 state_cache[state_ord[n]]); 904 if (maxprint > 0 && count >= maxprint) 905 break; 906 } 907 } 908 909 /* rule display */ 910 911 struct pf_rule *rules = NULL; 912 u_int32_t alloc_rules = 0; 913 914 int 915 select_rules(void) 916 { 917 num_disp = num_rules; 918 return (0); 919 } 920 921 922 void 923 add_rule_alloc(u_int32_t nr) 924 { 925 if (nr == 0) 926 return; 927 928 num_rules += nr; 929 930 if (rules == NULL) { 931 rules = reallocarray(NULL, num_rules, sizeof(struct pf_rule)); 932 if (rules == NULL) 933 err(1, "malloc"); 934 alloc_rules = num_rules; 935 } else if (num_rules > alloc_rules) { 936 rules = reallocarray(rules, num_rules, sizeof(struct pf_rule)); 937 if (rules == NULL) 938 err(1, "realloc"); 939 alloc_rules = num_rules; 940 } 941 } 942 943 int label_length; 944 945 int 946 read_anchor_rules(char *anchor) 947 { 948 struct pfioc_rule pr; 949 u_int32_t nr, num, off; 950 int len; 951 952 if (pf_dev < 0) 953 return (-1); 954 955 memset(&pr, 0, sizeof(pr)); 956 strlcpy(pr.anchor, anchor, sizeof(pr.anchor)); 957 958 if (ioctl(pf_dev, DIOCGETRULES, &pr) == -1) { 959 error("anchor %s: %s", anchor, strerror(errno)); 960 return (-1); 961 } 962 963 off = num_rules; 964 num = pr.nr; 965 add_rule_alloc(num); 966 967 for (nr = 0; nr < num; ++nr) { 968 pr.nr = nr; 969 if (ioctl(pf_dev, DIOCGETRULE, &pr) == -1) { 970 error("DIOCGETRULE: %s", strerror(errno)); 971 return (-1); 972 } 973 /* XXX overload pr.anchor, to store a pointer to 974 * anchor name */ 975 pr.rule.anchor = (struct pf_anchor *) anchor; 976 len = strlen(pr.rule.label); 977 if (len > label_length) 978 label_length = len; 979 rules[off + nr] = pr.rule; 980 } 981 982 return (num); 983 } 984 985 struct anchor_name { 986 char name[PATH_MAX]; 987 struct anchor_name *next; 988 u_int32_t ref; 989 }; 990 991 struct anchor_name *anchor_root = NULL; 992 struct anchor_name *anchor_end = NULL; 993 struct anchor_name *anchor_free = NULL; 994 995 struct anchor_name* 996 alloc_anchor_name(const char *path) 997 { 998 struct anchor_name *a; 999 1000 a = anchor_free; 1001 if (a == NULL) { 1002 a = malloc(sizeof(struct anchor_name)); 1003 if (a == NULL) 1004 return (NULL); 1005 } else 1006 anchor_free = a->next; 1007 1008 if (anchor_root == NULL) 1009 anchor_end = a; 1010 1011 a->next = anchor_root; 1012 anchor_root = a; 1013 1014 a->ref = 0; 1015 strlcpy(a->name, path, sizeof(a->name)); 1016 return (a); 1017 } 1018 1019 void 1020 reset_anchor_names(void) 1021 { 1022 if (anchor_end == NULL) 1023 return; 1024 1025 anchor_end->next = anchor_free; 1026 anchor_free = anchor_root; 1027 anchor_root = anchor_end = NULL; 1028 } 1029 1030 struct pfioc_ruleset ruleset; 1031 char *rs_end = NULL; 1032 1033 int 1034 read_rulesets(const char *path) 1035 { 1036 char *pre; 1037 struct anchor_name *a; 1038 u_int32_t nr, ns; 1039 int len; 1040 1041 if (path == NULL) 1042 ruleset.path[0] = '\0'; 1043 else if (strlcpy(ruleset.path, path, sizeof(ruleset.path)) >= 1044 sizeof(ruleset.path)) 1045 return (-1); 1046 1047 /* a persistent storage for anchor names */ 1048 a = alloc_anchor_name(ruleset.path); 1049 if (a == NULL) 1050 return (-1); 1051 1052 len = read_anchor_rules(a->name); 1053 if (len < 0) 1054 return (-1); 1055 1056 a->ref += len; 1057 1058 if (ioctl(pf_dev, DIOCGETRULESETS, &ruleset) == -1) { 1059 error("DIOCGETRULESETS: %s", strerror(errno)); 1060 return (-1); 1061 } 1062 1063 ns = ruleset.nr; 1064 1065 if (rs_end == NULL) 1066 rs_end = ruleset.path + sizeof(ruleset.path); 1067 1068 /* 'pre' tracks the previous level on the anchor */ 1069 pre = strchr(ruleset.path, 0); 1070 len = rs_end - pre; 1071 if (len < 1) 1072 return (-1); 1073 --len; 1074 1075 for (nr = 0; nr < ns; ++nr) { 1076 ruleset.nr = nr; 1077 if (ioctl(pf_dev, DIOCGETRULESET, &ruleset) == -1) { 1078 error("DIOCGETRULESET: %s", strerror(errno)); 1079 return (-1); 1080 } 1081 *pre = '/'; 1082 if (strlcpy(pre + 1, ruleset.name, len) < len) 1083 read_rulesets(ruleset.path); 1084 *pre = '\0'; 1085 } 1086 1087 return (0); 1088 } 1089 1090 void 1091 compute_anchor_field(void) 1092 { 1093 struct anchor_name *a; 1094 int sum, cnt, mx, nx; 1095 sum = cnt = mx = 0; 1096 1097 for (a = anchor_root; a != NULL; a = a->next, cnt++) { 1098 int len; 1099 if (a->ref == 0) 1100 continue; 1101 len = strlen(a->name); 1102 sum += len; 1103 if (len > mx) 1104 mx = len; 1105 } 1106 1107 nx = sum/cnt; 1108 if (nx < ANCHOR_FLD_SIZE) 1109 nx = (mx < ANCHOR_FLD_SIZE) ? mx : ANCHOR_FLD_SIZE; 1110 1111 if (FLD_ANCHOR->max_width != mx || 1112 FLD_ANCHOR->norm_width != nx) { 1113 FLD_ANCHOR->max_width = mx; 1114 FLD_ANCHOR->norm_width = nx; 1115 field_setup(); 1116 need_update = 1; 1117 } 1118 } 1119 1120 int 1121 read_rules(void) 1122 { 1123 int ret, nw, mw; 1124 num_rules = 0; 1125 1126 if (pf_dev == -1) 1127 return (-1); 1128 1129 label_length = MIN_LABEL_SIZE; 1130 1131 reset_anchor_names(); 1132 ret = read_rulesets(NULL); 1133 compute_anchor_field(); 1134 1135 nw = mw = label_length; 1136 if (nw > 16) 1137 nw = 16; 1138 1139 if (FLD_LABEL->norm_width != nw || 1140 FLD_LABEL->max_width != mw) { 1141 FLD_LABEL->norm_width = nw; 1142 FLD_LABEL->max_width = mw; 1143 field_setup(); 1144 need_update = 1; 1145 } 1146 1147 num_disp = num_rules; 1148 return (ret); 1149 } 1150 1151 void 1152 tb_print_addrw(struct pf_addr_wrap *addr, struct pf_addr *mask, u_int8_t af) 1153 { 1154 switch (addr->type) { 1155 case PF_ADDR_ADDRMASK: 1156 tb_print_addr(&addr->v.a.addr, mask, af); 1157 break; 1158 case PF_ADDR_NOROUTE: 1159 tbprintf("noroute"); 1160 break; 1161 case PF_ADDR_DYNIFTL: 1162 tbprintf("(%s)", addr->v.ifname); 1163 break; 1164 case PF_ADDR_TABLE: 1165 tbprintf("<%s>", addr->v.tblname); 1166 break; 1167 default: 1168 tbprintf("UNKNOWN"); 1169 break; 1170 } 1171 } 1172 1173 void 1174 tb_print_op(u_int8_t op, const char *a1, const char *a2) 1175 { 1176 if (op == PF_OP_IRG) 1177 tbprintf("%s >< %s ", a1, a2); 1178 else if (op == PF_OP_XRG) 1179 tbprintf("%s <> %s ", a1, a2); 1180 else if (op == PF_OP_RRG) 1181 tbprintf("%s:%s ", a1, a2); 1182 else if (op == PF_OP_EQ) 1183 tbprintf("= %s ", a1); 1184 else if (op == PF_OP_NE) 1185 tbprintf("!= %s ", a1); 1186 else if (op == PF_OP_LT) 1187 tbprintf("< %s ", a1); 1188 else if (op == PF_OP_LE) 1189 tbprintf("<= %s ", a1); 1190 else if (op == PF_OP_GT) 1191 tbprintf("> %s ", a1); 1192 else if (op == PF_OP_GE) 1193 tbprintf(">= %s ", a1); 1194 } 1195 1196 void 1197 tb_print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, char *proto) 1198 { 1199 char a1[6], a2[6]; 1200 struct servent *s = getservbyport(p1, proto); 1201 1202 p1 = ntohs(p1); 1203 p2 = ntohs(p2); 1204 snprintf(a1, sizeof(a1), "%u", p1); 1205 snprintf(a2, sizeof(a2), "%u", p2); 1206 tbprintf("port "); 1207 if (s != NULL && (op == PF_OP_EQ || op == PF_OP_NE)) 1208 tb_print_op(op, s->s_name, a2); 1209 else 1210 tb_print_op(op, a1, a2); 1211 } 1212 1213 void 1214 tb_print_fromto(struct pf_rule_addr *src, struct pf_rule_addr *dst, 1215 u_int8_t af, u_int8_t proto) 1216 { 1217 if ( 1218 PF_AZERO(PT_ADDR(src), AF_INET6) && 1219 PF_AZERO(PT_ADDR(dst), AF_INET6) && 1220 ! PT_NOROUTE(src) && ! PT_NOROUTE(dst) && 1221 PF_AZERO(PT_MASK(src), AF_INET6) && 1222 PF_AZERO(PT_MASK(dst), AF_INET6) && 1223 !src->port_op && !dst->port_op) 1224 tbprintf("all "); 1225 else { 1226 tbprintf("from "); 1227 if (PT_NOROUTE(src)) 1228 tbprintf("no-route "); 1229 else if (PF_AZERO(PT_ADDR(src), AF_INET6) && 1230 PF_AZERO(PT_MASK(src), AF_INET6)) 1231 tbprintf("any "); 1232 else { 1233 if (src->neg) 1234 tbprintf("! "); 1235 tb_print_addrw(&src->addr, PT_MASK(src), af); 1236 tbprintf(" "); 1237 } 1238 if (src->port_op) 1239 tb_print_port(src->port_op, src->port[0], 1240 src->port[1], 1241 proto == IPPROTO_TCP ? "tcp" : "udp"); 1242 1243 tbprintf("to "); 1244 if (PT_NOROUTE(dst)) 1245 tbprintf("no-route "); 1246 else if (PF_AZERO(PT_ADDR(dst), AF_INET6) && 1247 PF_AZERO(PT_MASK(dst), AF_INET6)) 1248 tbprintf("any "); 1249 else { 1250 if (dst->neg) 1251 tbprintf("! "); 1252 tb_print_addrw(&dst->addr, PT_MASK(dst), af); 1253 tbprintf(" "); 1254 } 1255 if (dst->port_op) 1256 tb_print_port(dst->port_op, dst->port[0], 1257 dst->port[1], 1258 proto == IPPROTO_TCP ? "tcp" : "udp"); 1259 } 1260 } 1261 1262 void 1263 tb_print_ugid(u_int8_t op, id_t i1, id_t i2, const char *t) 1264 { 1265 char a1[11], a2[11]; 1266 1267 snprintf(a1, sizeof(a1), "%u", i1); 1268 snprintf(a2, sizeof(a2), "%u", i2); 1269 1270 tbprintf("%s ", t); 1271 if (i1 == -1 && (op == PF_OP_EQ || op == PF_OP_NE)) 1272 tb_print_op(op, "unknown", a2); 1273 else 1274 tb_print_op(op, a1, a2); 1275 } 1276 1277 void 1278 tb_print_flags(u_int8_t f) 1279 { 1280 const char *tcpflags = "FSRPAUEW"; 1281 int i; 1282 1283 for (i = 0; tcpflags[i]; ++i) 1284 if (f & (1 << i)) 1285 tbprintf("%c", tcpflags[i]); 1286 } 1287 1288 void 1289 print_rule(struct pf_rule *pr) 1290 { 1291 static const char *actiontypes[] = { "Pass", "Block", "Scrub", 1292 "no Scrub", "Nat", "no Nat", "Binat", "no Binat", "Rdr", 1293 "no Rdr", "SynProxy Block", "Defer", "Match" }; 1294 int numact = sizeof(actiontypes) / sizeof(char *); 1295 1296 static const char *routetypes[] = { "", "fastroute", "route-to", 1297 "dup-to", "reply-to" }; 1298 1299 int numroute = sizeof(routetypes) / sizeof(char *); 1300 1301 if (pr == NULL) return; 1302 1303 print_fld_str(FLD_LABEL, pr->label); 1304 print_fld_size(FLD_STATS, pr->states_tot); 1305 1306 print_fld_size(FLD_PKTS, pr->packets[0] + pr->packets[1]); 1307 print_fld_size(FLD_BYTES, pr->bytes[0] + pr->bytes[1]); 1308 1309 print_fld_uint(FLD_RULE, pr->nr); 1310 if (pr->direction == PF_OUT) 1311 print_fld_str(FLD_DIR, "Out"); 1312 else if (pr->direction == PF_IN) 1313 print_fld_str(FLD_DIR, "In"); 1314 else 1315 print_fld_str(FLD_DIR, "Any"); 1316 1317 if (pr->quick) 1318 print_fld_str(FLD_QUICK, "Quick"); 1319 1320 if (pr->keep_state == PF_STATE_NORMAL) 1321 print_fld_str(FLD_KST, "Keep"); 1322 else if (pr->keep_state == PF_STATE_MODULATE) 1323 print_fld_str(FLD_KST, "Mod"); 1324 else if (pr->keep_state == PF_STATE_SYNPROXY) 1325 print_fld_str(FLD_KST, "Syn"); 1326 if (pr->log == 1) 1327 print_fld_str(FLD_LOG, "Log"); 1328 else if (pr->log == 2) 1329 print_fld_str(FLD_LOG, "All"); 1330 1331 if (pr->action >= numact) 1332 print_fld_uint(FLD_ACTION, pr->action); 1333 else print_fld_str(FLD_ACTION, actiontypes[pr->action]); 1334 1335 if (pr->proto) { 1336 struct protoent *p = getprotobynumber(pr->proto); 1337 1338 if (p != NULL) 1339 print_fld_str(FLD_PROTO, p->p_name); 1340 else 1341 print_fld_uint(FLD_PROTO, pr->proto); 1342 } 1343 1344 if (pr->ifname[0]) { 1345 tb_start(); 1346 if (pr->ifnot) 1347 tbprintf("!"); 1348 tbprintf("%s", pr->ifname); 1349 print_fld_tb(FLD_IF); 1350 } 1351 if (pr->max_states) 1352 print_fld_uint(FLD_STMAX, pr->max_states); 1353 1354 /* print info field */ 1355 1356 tb_start(); 1357 1358 if (pr->action == PF_DROP) { 1359 if (pr->rule_flag & PFRULE_RETURNRST) 1360 tbprintf("return-rst "); 1361 #ifdef PFRULE_RETURN 1362 else if (pr->rule_flag & PFRULE_RETURN) 1363 tbprintf("return "); 1364 #endif 1365 #ifdef PFRULE_RETURNICMP 1366 else if (pr->rule_flag & PFRULE_RETURNICMP) 1367 tbprintf("return-icmp "); 1368 #endif 1369 else 1370 tbprintf("drop "); 1371 } 1372 1373 if (pr->rt > 0 && pr->rt < numroute) { 1374 tbprintf("%s ", routetypes[pr->rt]); 1375 } 1376 1377 if (pr->af) { 1378 if (pr->af == AF_INET) 1379 tbprintf("inet "); 1380 else 1381 tbprintf("inet6 "); 1382 } 1383 1384 tb_print_fromto(&pr->src, &pr->dst, pr->af, pr->proto); 1385 1386 if (pr->uid.op) 1387 tb_print_ugid(pr->uid.op, pr->uid.uid[0], pr->uid.uid[1], 1388 "user"); 1389 if (pr->gid.op) 1390 tb_print_ugid(pr->gid.op, pr->gid.gid[0], pr->gid.gid[1], 1391 "group"); 1392 1393 if (pr->action == PF_PASS && 1394 (pr->proto == 0 || pr->proto == IPPROTO_TCP) && 1395 (pr->flags != TH_SYN || pr->flagset != (TH_SYN | TH_ACK) )) { 1396 tbprintf("flags "); 1397 if (pr->flags || pr->flagset) { 1398 tb_print_flags(pr->flags); 1399 tbprintf("/"); 1400 tb_print_flags(pr->flagset); 1401 } else 1402 tbprintf("any "); 1403 } 1404 1405 tbprintf(" "); 1406 1407 if (pr->tos) 1408 tbprintf("tos 0x%2.2x ", pr->tos); 1409 #ifdef PFRULE_FRAGMENT 1410 if (pr->rule_flag & PFRULE_FRAGMENT) 1411 tbprintf("fragment "); 1412 #endif 1413 #ifdef PFRULE_NODF 1414 if (pr->rule_flag & PFRULE_NODF) 1415 tbprintf("no-df "); 1416 #endif 1417 #ifdef PFRULE_RANDOMID 1418 if (pr->rule_flag & PFRULE_RANDOMID) 1419 tbprintf("random-id "); 1420 #endif 1421 if (pr->min_ttl) 1422 tbprintf("min-ttl %d ", pr->min_ttl); 1423 if (pr->max_mss) 1424 tbprintf("max-mss %d ", pr->max_mss); 1425 if (pr->allow_opts) 1426 tbprintf("allow-opts "); 1427 1428 /* XXX more missing */ 1429 1430 if (pr->qname[0] && pr->pqname[0]) 1431 tbprintf("queue(%s, %s) ", pr->qname, pr->pqname); 1432 else if (pr->qname[0]) 1433 tbprintf("queue %s ", pr->qname); 1434 1435 if (pr->tagname[0]) 1436 tbprintf("tag %s ", pr->tagname); 1437 if (pr->match_tagname[0]) { 1438 if (pr->match_tag_not) 1439 tbprintf("! "); 1440 tbprintf("tagged %s ", pr->match_tagname); 1441 } 1442 1443 print_fld_tb(FLD_RINFO); 1444 1445 /* XXX anchor field overloaded with anchor name */ 1446 print_fld_str(FLD_ANCHOR, (char *)pr->anchor); 1447 tb_end(); 1448 1449 end_line(); 1450 } 1451 1452 void 1453 print_rules(void) 1454 { 1455 u_int32_t n, count = 0; 1456 1457 for (n = dispstart; n < num_rules; n++) { 1458 print_rule(rules + n); 1459 count ++; 1460 if (maxprint > 0 && count >= maxprint) 1461 break; 1462 } 1463 } 1464 1465 /* queue display */ 1466 struct pfctl_queue_node * 1467 pfctl_find_queue_node(const char *qname, const char *ifname) 1468 { 1469 struct pfctl_queue_node *node; 1470 1471 TAILQ_FOREACH(node, &qnodes, entries) 1472 if (!strcmp(node->qs.qname, qname) 1473 && !(strcmp(node->qs.ifname, ifname))) 1474 return (node); 1475 return (NULL); 1476 } 1477 1478 void 1479 pfctl_insert_queue_node(const struct pf_queuespec qs, 1480 const struct queue_stats qstats) 1481 { 1482 struct pfctl_queue_node *node, *parent; 1483 1484 node = calloc(1, sizeof(struct pfctl_queue_node)); 1485 if (node == NULL) 1486 err(1, "pfctl_insert_queue_node: calloc"); 1487 memcpy(&node->qs, &qs, sizeof(qs)); 1488 memcpy(&node->qstats, &qstats, sizeof(qstats)); 1489 1490 if (node->qs.parent[0]) { 1491 parent = pfctl_find_queue_node(node->qs.parent, 1492 node->qs.ifname); 1493 if (parent) 1494 node->depth = parent->depth + 1; 1495 } 1496 1497 TAILQ_INSERT_TAIL(&qnodes, node, entries); 1498 } 1499 1500 int 1501 pfctl_update_qstats(void) 1502 { 1503 struct pfctl_queue_node *node; 1504 struct pfioc_queue pq; 1505 struct pfioc_qstats pqs; 1506 u_int32_t mnr, nr; 1507 struct queue_stats qstats; 1508 static u_int32_t last_ticket; 1509 1510 memset(&pq, 0, sizeof(pq)); 1511 memset(&pqs, 0, sizeof(pqs)); 1512 memset(&qstats, 0, sizeof(qstats)); 1513 1514 if (pf_dev < 0) 1515 return (-1); 1516 1517 if (ioctl(pf_dev, DIOCGETQUEUES, &pq) == -1) { 1518 error("DIOCGETQUEUES: %s", strerror(errno)); 1519 return (-1); 1520 } 1521 1522 /* if a new set is found, start over */ 1523 if (pq.ticket != last_ticket) 1524 while ((node = TAILQ_FIRST(&qnodes)) != NULL) { 1525 TAILQ_REMOVE(&qnodes, node, entries); 1526 free(node); 1527 } 1528 last_ticket = pq.ticket; 1529 1530 num_queues = mnr = pq.nr; 1531 for (nr = 0; nr < mnr; ++nr) { 1532 pqs.nr = nr; 1533 pqs.ticket = pq.ticket; 1534 pqs.buf = &qstats.data; 1535 pqs.nbytes = sizeof(qstats.data); 1536 if (ioctl(pf_dev, DIOCGETQSTATS, &pqs) == -1) { 1537 error("DIOCGETQSTATS: %s", strerror(errno)); 1538 return (-1); 1539 } 1540 qstats.valid = 1; 1541 gettimeofday(&qstats.timestamp, NULL); 1542 if ((node = pfctl_find_queue_node(pqs.queue.qname, 1543 pqs.queue.ifname)) != NULL) { 1544 memcpy(&node->qstats_last, &node->qstats, 1545 sizeof(struct queue_stats)); 1546 memcpy(&node->qstats, &qstats, 1547 sizeof(struct queue_stats)); 1548 } else { 1549 pfctl_insert_queue_node(pqs.queue, qstats); 1550 } 1551 } 1552 return (0); 1553 } 1554 1555 int 1556 select_queues(void) 1557 { 1558 num_disp = num_queues; 1559 return (0); 1560 } 1561 1562 int 1563 read_queues(void) 1564 { 1565 num_disp = num_queues = 0; 1566 1567 if (pfctl_update_qstats() < 0) 1568 return (-1); 1569 num_disp = num_queues; 1570 1571 return(0); 1572 } 1573 1574 double 1575 calc_interval(struct timeval *cur_time, struct timeval *last_time) 1576 { 1577 double sec; 1578 1579 sec = (double)(cur_time->tv_sec - last_time->tv_sec) + 1580 (double)(cur_time->tv_usec - last_time->tv_usec) / 1000000; 1581 1582 return (sec); 1583 } 1584 1585 double 1586 calc_rate(u_int64_t new_bytes, u_int64_t last_bytes, double interval) 1587 { 1588 double rate; 1589 1590 rate = (double)(new_bytes - last_bytes) / interval; 1591 return (rate); 1592 } 1593 1594 double 1595 calc_pps(u_int64_t new_pkts, u_int64_t last_pkts, double interval) 1596 { 1597 double pps; 1598 1599 pps = (double)(new_pkts - last_pkts) / interval; 1600 return (pps); 1601 } 1602 1603 void 1604 print_queue_node(struct pfctl_queue_node *node) 1605 { 1606 u_int rate, rtmp; 1607 int i; 1608 double interval, pps, bps; 1609 static const char unit[] = " KMG"; 1610 1611 tb_start(); 1612 for (i = 0; i < node->depth; i++) 1613 tbprintf(" "); 1614 tbprintf("%s", node->qs.qname); 1615 if (i == 0 && node->qs.ifname[0]) 1616 tbprintf(" on %s ", node->qs.ifname); 1617 print_fld_tb(FLD_QUEUE); 1618 1619 // XXX: missing min, max, burst 1620 tb_start(); 1621 rate = node->qs.linkshare.m2.absolute; 1622 for (i = 0; rate > 9999 && i <= 3; i++) { 1623 rtmp = rate / 1000; 1624 if (rtmp <= 9999) 1625 rtmp += (rate % 1000) / 500; 1626 rate = rtmp; 1627 } 1628 if (rate == 0 && (node->qs.flags & PFQS_FLOWQUEUE)) { 1629 /* 1630 * XXX We're abusing the fact that 'flows' in 1631 * the fqcodel_stats structure is at the same 1632 * spot as the 'period' in hfsc_class_stats. 1633 */ 1634 tbprintf("%u", node->qstats.data.period); 1635 } else 1636 tbprintf("%u%c", rate, unit[i]); 1637 print_fld_tb(FLD_BANDW); 1638 1639 print_fld_str(FLD_SCHED, node->qs.flags & PFQS_FLOWQUEUE ? 1640 "flow" : "fifo"); 1641 1642 if (node->qstats.valid && node->qstats_last.valid) 1643 interval = calc_interval(&node->qstats.timestamp, 1644 &node->qstats_last.timestamp); 1645 else 1646 interval = 0; 1647 1648 print_fld_size(FLD_PKTS, node->qstats.data.xmit_cnt.packets); 1649 print_fld_size(FLD_BYTES, node->qstats.data.xmit_cnt.bytes); 1650 print_fld_size(FLD_DROPP, node->qstats.data.drop_cnt.packets); 1651 print_fld_size(FLD_DROPB, node->qstats.data.drop_cnt.bytes); 1652 print_fld_size(FLD_QLEN, node->qstats.data.qlength); 1653 1654 if (interval > 0) { 1655 pps = calc_pps(node->qstats.data.xmit_cnt.packets, 1656 node->qstats_last.data.xmit_cnt.packets, interval); 1657 bps = calc_rate(node->qstats.data.xmit_cnt.bytes, 1658 node->qstats_last.data.xmit_cnt.bytes, interval); 1659 1660 tb_start(); 1661 if (pps > 0 && pps < 1) 1662 tbprintf("%-3.1lf", pps); 1663 else 1664 tbprintf("%u", (unsigned int)pps); 1665 1666 print_fld_tb(FLD_PKTSPS); 1667 print_fld_bw(FLD_BYTESPS, bps); 1668 } 1669 } 1670 1671 void 1672 print_queues(void) 1673 { 1674 uint32_t n, count, start; 1675 struct pfctl_queue_node *node; 1676 1677 n = count = 0; 1678 start = dispstart; 1679 1680 TAILQ_FOREACH(node, &qnodes, entries) { 1681 if (n < start) { 1682 n++; 1683 continue; 1684 } 1685 print_queue_node(node); 1686 end_line(); 1687 count++; 1688 if (maxprint > 0 && count >= maxprint) 1689 return; 1690 } 1691 } 1692 1693 /* main program functions */ 1694 1695 void 1696 update_cache(void) 1697 { 1698 static int pstate = -1; 1699 if (pstate == cachestates) 1700 return; 1701 1702 pstate = cachestates; 1703 if (cachestates) { 1704 show_field(FLD_SI); 1705 show_field(FLD_SP); 1706 gotsig_alarm = 1; 1707 } else { 1708 hide_field(FLD_SI); 1709 hide_field(FLD_SP); 1710 need_update = 1; 1711 } 1712 field_setup(); 1713 } 1714 1715 int 1716 initpftop(void) 1717 { 1718 struct pf_status status; 1719 field_view *v; 1720 int cachesize = DEFAULT_CACHE_SIZE; 1721 1722 v = views; 1723 while(v->name != NULL) 1724 add_view(v++); 1725 1726 pf_dev = open("/dev/pf", O_RDONLY); 1727 if (pf_dev == -1) { 1728 alloc_buf(0); 1729 } else if (ioctl(pf_dev, DIOCGETSTATUS, &status) == -1) { 1730 warn("DIOCGETSTATUS"); 1731 alloc_buf(0); 1732 } else 1733 alloc_buf(status.states); 1734 1735 /* initialize cache with given size */ 1736 if (cache_init(cachesize)) 1737 warnx("Failed to initialize cache."); 1738 else if (interactive && cachesize > 0) 1739 cachestates = 1; 1740 1741 update_cache(); 1742 1743 show_field(FLD_STMAX); 1744 show_field(FLD_ANCHOR); 1745 1746 return (1); 1747 } 1748