1223637Sbz/* $OpenBSD: pfctl_table.c,v 1.67 2008/06/10 20:55:02 mcbride Exp $ */ 2126353Smlaier 3126353Smlaier/* 4126353Smlaier * Copyright (c) 2002 Cedric Berger 5126353Smlaier * All rights reserved. 6126353Smlaier * 7126353Smlaier * Redistribution and use in source and binary forms, with or without 8126353Smlaier * modification, are permitted provided that the following conditions 9126353Smlaier * are met: 10126353Smlaier * 11126353Smlaier * - Redistributions of source code must retain the above copyright 12126353Smlaier * notice, this list of conditions and the following disclaimer. 13126353Smlaier * - Redistributions in binary form must reproduce the above 14126353Smlaier * copyright notice, this list of conditions and the following 15126353Smlaier * disclaimer in the documentation and/or other materials provided 16126353Smlaier * with the distribution. 17126353Smlaier * 18126353Smlaier * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19126353Smlaier * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20126353Smlaier * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21126353Smlaier * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22126353Smlaier * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 23126353Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 24126353Smlaier * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25126353Smlaier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26126353Smlaier * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27126353Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 28126353Smlaier * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29126353Smlaier * POSSIBILITY OF SUCH DAMAGE. 30126353Smlaier * 31126353Smlaier */ 32126353Smlaier 33127082Sobrien#include <sys/cdefs.h> 34127082Sobrien__FBSDID("$FreeBSD$"); 35127082Sobrien 36126353Smlaier#include <sys/types.h> 37126353Smlaier#include <sys/ioctl.h> 38126353Smlaier#include <sys/socket.h> 39126353Smlaier 40126353Smlaier#include <net/if.h> 41126353Smlaier#include <net/pfvar.h> 42126353Smlaier#include <arpa/inet.h> 43126353Smlaier 44126353Smlaier#include <ctype.h> 45126353Smlaier#include <err.h> 46126353Smlaier#include <errno.h> 47126353Smlaier#include <netdb.h> 48126353Smlaier#include <stdarg.h> 49126353Smlaier#include <stdio.h> 50126353Smlaier#include <stdlib.h> 51126353Smlaier#include <string.h> 52126353Smlaier#include <time.h> 53126353Smlaier 54126353Smlaier#include "pfctl_parser.h" 55126353Smlaier#include "pfctl.h" 56126353Smlaier 57126353Smlaierextern void usage(void); 58126353Smlaierstatic int pfctl_table(int, char *[], char *, const char *, char *, 59145840Smlaier const char *, int); 60126353Smlaierstatic void print_table(struct pfr_table *, int, int); 61126353Smlaierstatic void print_tstats(struct pfr_tstats *, int); 62126353Smlaierstatic int load_addr(struct pfr_buffer *, int, char *[], char *, int); 63126353Smlaierstatic void print_addrx(struct pfr_addr *, struct pfr_addr *, int); 64126353Smlaierstatic void print_astats(struct pfr_astats *, int); 65126353Smlaierstatic void radix_perror(void); 66126353Smlaierstatic void xprintf(int, const char *, ...); 67171172Smlaierstatic void print_iface(struct pfi_kif *, int); 68126353Smlaier 69126353Smlaierstatic const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { 70126353Smlaier { "In/Block:", "In/Pass:", "In/XPass:" }, 71126353Smlaier { "Out/Block:", "Out/Pass:", "Out/XPass:" } 72126353Smlaier}; 73126353Smlaier 74130617Smlaierstatic const char *istats_text[2][2][2] = { 75130617Smlaier { { "In4/Pass:", "In4/Block:" }, { "Out4/Pass:", "Out4/Block:" } }, 76130617Smlaier { { "In6/Pass:", "In6/Block:" }, { "Out6/Pass:", "Out6/Block:" } } 77130617Smlaier}; 78130617Smlaier 79126353Smlaier#define RVTEST(fct) do { \ 80126353Smlaier if ((!(opts & PF_OPT_NOACTION) || \ 81126353Smlaier (opts & PF_OPT_DUMMYACTION)) && \ 82126353Smlaier (fct)) { \ 83126353Smlaier radix_perror(); \ 84126353Smlaier goto _error; \ 85126353Smlaier } \ 86126353Smlaier } while (0) 87126353Smlaier 88126353Smlaier#define CREATE_TABLE do { \ 89126353Smlaier table.pfrt_flags |= PFR_TFLAG_PERSIST; \ 90134175Smlaier if ((!(opts & PF_OPT_NOACTION) || \ 91134175Smlaier (opts & PF_OPT_DUMMYACTION)) && \ 92134175Smlaier (pfr_add_tables(&table, 1, &nadd, flags)) && \ 93134175Smlaier (errno != EPERM)) { \ 94134175Smlaier radix_perror(); \ 95134175Smlaier goto _error; \ 96134175Smlaier } \ 97126353Smlaier if (nadd) { \ 98126353Smlaier warn_namespace_collision(table.pfrt_name); \ 99126353Smlaier xprintf(opts, "%d table created", nadd); \ 100126353Smlaier if (opts & PF_OPT_NOACTION) \ 101126353Smlaier return (0); \ 102126353Smlaier } \ 103126353Smlaier table.pfrt_flags &= ~PFR_TFLAG_PERSIST; \ 104126353Smlaier } while(0) 105126353Smlaier 106126353Smlaierint 107145840Smlaierpfctl_clear_tables(const char *anchor, int opts) 108126353Smlaier{ 109145840Smlaier return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts); 110126353Smlaier} 111126353Smlaier 112126353Smlaierint 113145840Smlaierpfctl_show_tables(const char *anchor, int opts) 114126353Smlaier{ 115145840Smlaier return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts); 116126353Smlaier} 117126353Smlaier 118126353Smlaierint 119126353Smlaierpfctl_command_tables(int argc, char *argv[], char *tname, 120145840Smlaier const char *command, char *file, const char *anchor, int opts) 121126353Smlaier{ 122126353Smlaier if (tname == NULL || command == NULL) 123126353Smlaier usage(); 124145840Smlaier return pfctl_table(argc, argv, tname, command, file, anchor, opts); 125126353Smlaier} 126126353Smlaier 127126353Smlaierint 128126353Smlaierpfctl_table(int argc, char *argv[], char *tname, const char *command, 129145840Smlaier char *file, const char *anchor, int opts) 130126353Smlaier{ 131130617Smlaier struct pfr_table table; 132130617Smlaier struct pfr_buffer b, b2; 133130617Smlaier struct pfr_addr *a, *a2; 134130617Smlaier int nadd = 0, ndel = 0, nchange = 0, nzero = 0; 135130617Smlaier int rv = 0, flags = 0, nmatch = 0; 136130617Smlaier void *p; 137126353Smlaier 138126353Smlaier if (command == NULL) 139126353Smlaier usage(); 140126353Smlaier if (opts & PF_OPT_NOACTION) 141126353Smlaier flags |= PFR_FLAG_DUMMY; 142126353Smlaier 143126353Smlaier bzero(&b, sizeof(b)); 144126353Smlaier bzero(&b2, sizeof(b2)); 145126353Smlaier bzero(&table, sizeof(table)); 146126353Smlaier if (tname != NULL) { 147126353Smlaier if (strlen(tname) >= PF_TABLE_NAME_SIZE) 148126353Smlaier usage(); 149126353Smlaier if (strlcpy(table.pfrt_name, tname, 150126353Smlaier sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 151126353Smlaier errx(1, "pfctl_table: strlcpy"); 152126353Smlaier } 153126353Smlaier if (strlcpy(table.pfrt_anchor, anchor, 154145840Smlaier sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor)) 155126353Smlaier errx(1, "pfctl_table: strlcpy"); 156126353Smlaier 157126353Smlaier if (!strcmp(command, "-F")) { 158126353Smlaier if (argc || file != NULL) 159126353Smlaier usage(); 160126353Smlaier RVTEST(pfr_clr_tables(&table, &ndel, flags)); 161126353Smlaier xprintf(opts, "%d tables deleted", ndel); 162126353Smlaier } else if (!strcmp(command, "-s")) { 163126353Smlaier b.pfrb_type = (opts & PF_OPT_VERBOSE2) ? 164126353Smlaier PFRB_TSTATS : PFRB_TABLES; 165126353Smlaier if (argc || file != NULL) 166126353Smlaier usage(); 167126353Smlaier for (;;) { 168126353Smlaier pfr_buf_grow(&b, b.pfrb_size); 169126353Smlaier b.pfrb_size = b.pfrb_msize; 170126353Smlaier if (opts & PF_OPT_VERBOSE2) 171126353Smlaier RVTEST(pfr_get_tstats(&table, 172126353Smlaier b.pfrb_caddr, &b.pfrb_size, flags)); 173126353Smlaier else 174126353Smlaier RVTEST(pfr_get_tables(&table, 175126353Smlaier b.pfrb_caddr, &b.pfrb_size, flags)); 176126353Smlaier if (b.pfrb_size <= b.pfrb_msize) 177126353Smlaier break; 178126353Smlaier } 179130617Smlaier 180171172Smlaier if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0) 181130617Smlaier pfctl_print_title("TABLES:"); 182130617Smlaier 183126353Smlaier PFRB_FOREACH(p, &b) 184126353Smlaier if (opts & PF_OPT_VERBOSE2) 185126353Smlaier print_tstats(p, opts & PF_OPT_DEBUG); 186126353Smlaier else 187126353Smlaier print_table(p, opts & PF_OPT_VERBOSE, 188126353Smlaier opts & PF_OPT_DEBUG); 189126353Smlaier } else if (!strcmp(command, "kill")) { 190126353Smlaier if (argc || file != NULL) 191126353Smlaier usage(); 192126353Smlaier RVTEST(pfr_del_tables(&table, 1, &ndel, flags)); 193126353Smlaier xprintf(opts, "%d table deleted", ndel); 194126353Smlaier } else if (!strcmp(command, "flush")) { 195126353Smlaier if (argc || file != NULL) 196126353Smlaier usage(); 197126353Smlaier RVTEST(pfr_clr_addrs(&table, &ndel, flags)); 198126353Smlaier xprintf(opts, "%d addresses deleted", ndel); 199126353Smlaier } else if (!strcmp(command, "add")) { 200126353Smlaier b.pfrb_type = PFRB_ADDRS; 201126353Smlaier if (load_addr(&b, argc, argv, file, 0)) 202126353Smlaier goto _error; 203126353Smlaier CREATE_TABLE; 204126353Smlaier if (opts & PF_OPT_VERBOSE) 205126353Smlaier flags |= PFR_FLAG_FEEDBACK; 206126353Smlaier RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, 207126353Smlaier &nadd, flags)); 208126353Smlaier xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size); 209126353Smlaier if (opts & PF_OPT_VERBOSE) 210126353Smlaier PFRB_FOREACH(a, &b) 211126353Smlaier if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 212126353Smlaier print_addrx(a, NULL, 213126353Smlaier opts & PF_OPT_USEDNS); 214126353Smlaier } else if (!strcmp(command, "delete")) { 215126353Smlaier b.pfrb_type = PFRB_ADDRS; 216126353Smlaier if (load_addr(&b, argc, argv, file, 0)) 217126353Smlaier goto _error; 218126353Smlaier if (opts & PF_OPT_VERBOSE) 219126353Smlaier flags |= PFR_FLAG_FEEDBACK; 220126353Smlaier RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size, 221126353Smlaier &ndel, flags)); 222126353Smlaier xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size); 223126353Smlaier if (opts & PF_OPT_VERBOSE) 224126353Smlaier PFRB_FOREACH(a, &b) 225126353Smlaier if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 226126353Smlaier print_addrx(a, NULL, 227126353Smlaier opts & PF_OPT_USEDNS); 228126353Smlaier } else if (!strcmp(command, "replace")) { 229126353Smlaier b.pfrb_type = PFRB_ADDRS; 230126353Smlaier if (load_addr(&b, argc, argv, file, 0)) 231126353Smlaier goto _error; 232126353Smlaier CREATE_TABLE; 233126353Smlaier if (opts & PF_OPT_VERBOSE) 234126353Smlaier flags |= PFR_FLAG_FEEDBACK; 235126353Smlaier for (;;) { 236126353Smlaier int sz2 = b.pfrb_msize; 237126353Smlaier 238126353Smlaier RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size, 239126353Smlaier &sz2, &nadd, &ndel, &nchange, flags)); 240126353Smlaier if (sz2 <= b.pfrb_msize) { 241126353Smlaier b.pfrb_size = sz2; 242126353Smlaier break; 243126353Smlaier } else 244126353Smlaier pfr_buf_grow(&b, sz2); 245126353Smlaier } 246126353Smlaier if (nadd) 247126353Smlaier xprintf(opts, "%d addresses added", nadd); 248126353Smlaier if (ndel) 249126353Smlaier xprintf(opts, "%d addresses deleted", ndel); 250126353Smlaier if (nchange) 251126353Smlaier xprintf(opts, "%d addresses changed", nchange); 252126353Smlaier if (!nadd && !ndel && !nchange) 253126353Smlaier xprintf(opts, "no changes"); 254126353Smlaier if (opts & PF_OPT_VERBOSE) 255126353Smlaier PFRB_FOREACH(a, &b) 256126353Smlaier if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 257126353Smlaier print_addrx(a, NULL, 258126353Smlaier opts & PF_OPT_USEDNS); 259171172Smlaier } else if (!strcmp(command, "expire")) { 260171172Smlaier const char *errstr; 261171172Smlaier u_int lifetime; 262171172Smlaier 263171172Smlaier b.pfrb_type = PFRB_ASTATS; 264171172Smlaier b2.pfrb_type = PFRB_ADDRS; 265171172Smlaier if (argc != 1 || file != NULL) 266171172Smlaier usage(); 267171172Smlaier lifetime = strtonum(*argv, 0, UINT_MAX, &errstr); 268171172Smlaier if (errstr) 269171172Smlaier errx(1, "expiry time: %s", errstr); 270171172Smlaier for (;;) { 271171172Smlaier pfr_buf_grow(&b, b.pfrb_size); 272171172Smlaier b.pfrb_size = b.pfrb_msize; 273171172Smlaier RVTEST(pfr_get_astats(&table, b.pfrb_caddr, 274171172Smlaier &b.pfrb_size, flags)); 275171172Smlaier if (b.pfrb_size <= b.pfrb_msize) 276171172Smlaier break; 277171172Smlaier } 278223637Sbz PFRB_FOREACH(p, &b) { 279223637Sbz ((struct pfr_astats *)p)->pfras_a.pfra_fback = 0; 280171172Smlaier if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero > 281223637Sbz lifetime) 282171172Smlaier if (pfr_buf_add(&b2, 283171172Smlaier &((struct pfr_astats *)p)->pfras_a)) 284171172Smlaier err(1, "duplicate buffer"); 285223637Sbz } 286171172Smlaier 287171172Smlaier if (opts & PF_OPT_VERBOSE) 288171172Smlaier flags |= PFR_FLAG_FEEDBACK; 289171172Smlaier RVTEST(pfr_del_addrs(&table, b2.pfrb_caddr, b2.pfrb_size, 290171172Smlaier &ndel, flags)); 291171172Smlaier xprintf(opts, "%d/%d addresses expired", ndel, b2.pfrb_size); 292171172Smlaier if (opts & PF_OPT_VERBOSE) 293171172Smlaier PFRB_FOREACH(a, &b2) 294171172Smlaier if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 295171172Smlaier print_addrx(a, NULL, 296171172Smlaier opts & PF_OPT_USEDNS); 297126353Smlaier } else if (!strcmp(command, "show")) { 298126353Smlaier b.pfrb_type = (opts & PF_OPT_VERBOSE) ? 299130617Smlaier PFRB_ASTATS : PFRB_ADDRS; 300126353Smlaier if (argc || file != NULL) 301126353Smlaier usage(); 302126353Smlaier for (;;) { 303126353Smlaier pfr_buf_grow(&b, b.pfrb_size); 304126353Smlaier b.pfrb_size = b.pfrb_msize; 305126353Smlaier if (opts & PF_OPT_VERBOSE) 306126353Smlaier RVTEST(pfr_get_astats(&table, b.pfrb_caddr, 307126353Smlaier &b.pfrb_size, flags)); 308126353Smlaier else 309126353Smlaier RVTEST(pfr_get_addrs(&table, b.pfrb_caddr, 310126353Smlaier &b.pfrb_size, flags)); 311126353Smlaier if (b.pfrb_size <= b.pfrb_msize) 312126353Smlaier break; 313126353Smlaier } 314126353Smlaier PFRB_FOREACH(p, &b) 315126353Smlaier if (opts & PF_OPT_VERBOSE) 316126353Smlaier print_astats(p, opts & PF_OPT_USEDNS); 317126353Smlaier else 318126353Smlaier print_addrx(p, NULL, opts & PF_OPT_USEDNS); 319126353Smlaier } else if (!strcmp(command, "test")) { 320126353Smlaier b.pfrb_type = PFRB_ADDRS; 321126353Smlaier b2.pfrb_type = PFRB_ADDRS; 322126353Smlaier 323126353Smlaier if (load_addr(&b, argc, argv, file, 1)) 324126353Smlaier goto _error; 325126353Smlaier if (opts & PF_OPT_VERBOSE2) { 326126353Smlaier flags |= PFR_FLAG_REPLACE; 327126353Smlaier PFRB_FOREACH(a, &b) 328126353Smlaier if (pfr_buf_add(&b2, a)) 329126353Smlaier err(1, "duplicate buffer"); 330126353Smlaier } 331126353Smlaier RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size, 332126353Smlaier &nmatch, flags)); 333126353Smlaier xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size); 334171172Smlaier if ((opts & PF_OPT_VERBOSE) && !(opts & PF_OPT_VERBOSE2)) 335126353Smlaier PFRB_FOREACH(a, &b) 336126353Smlaier if (a->pfra_fback == PFR_FB_MATCH) 337126353Smlaier print_addrx(a, NULL, 338126353Smlaier opts & PF_OPT_USEDNS); 339126353Smlaier if (opts & PF_OPT_VERBOSE2) { 340126353Smlaier a2 = NULL; 341126353Smlaier PFRB_FOREACH(a, &b) { 342126353Smlaier a2 = pfr_buf_next(&b2, a2); 343126353Smlaier print_addrx(a2, a, opts & PF_OPT_USEDNS); 344126353Smlaier } 345126353Smlaier } 346126353Smlaier if (nmatch < b.pfrb_size) 347126353Smlaier rv = 2; 348126353Smlaier } else if (!strcmp(command, "zero")) { 349126353Smlaier if (argc || file != NULL) 350126353Smlaier usage(); 351126353Smlaier flags |= PFR_FLAG_ADDRSTOO; 352126353Smlaier RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags)); 353126353Smlaier xprintf(opts, "%d table/stats cleared", nzero); 354126353Smlaier } else 355126353Smlaier warnx("pfctl_table: unknown command '%s'", command); 356126353Smlaier goto _cleanup; 357126353Smlaier 358126353Smlaier_error: 359126353Smlaier rv = -1; 360126353Smlaier_cleanup: 361126353Smlaier pfr_buf_clear(&b); 362126353Smlaier pfr_buf_clear(&b2); 363126353Smlaier return (rv); 364126353Smlaier} 365126353Smlaier 366126353Smlaiervoid 367126353Smlaierprint_table(struct pfr_table *ta, int verbose, int debug) 368126353Smlaier{ 369126353Smlaier if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE)) 370126353Smlaier return; 371126353Smlaier if (verbose) { 372223637Sbz printf("%c%c%c%c%c%c%c\t%s", 373126353Smlaier (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-', 374126353Smlaier (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-', 375126353Smlaier (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-', 376126353Smlaier (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-', 377126353Smlaier (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-', 378126353Smlaier (ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-', 379223637Sbz (ta->pfrt_flags & PFR_TFLAG_COUNTERS) ? 'C' : '-', 380126353Smlaier ta->pfrt_name); 381126353Smlaier if (ta->pfrt_anchor[0]) 382130617Smlaier printf("\t%s", ta->pfrt_anchor); 383126353Smlaier puts(""); 384126353Smlaier } else 385126353Smlaier puts(ta->pfrt_name); 386126353Smlaier} 387126353Smlaier 388126353Smlaiervoid 389126353Smlaierprint_tstats(struct pfr_tstats *ts, int debug) 390126353Smlaier{ 391126353Smlaier time_t time = ts->pfrts_tzero; 392126353Smlaier int dir, op; 393126353Smlaier 394126353Smlaier if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) 395126353Smlaier return; 396126353Smlaier print_table(&ts->pfrts_t, 1, debug); 397126353Smlaier printf("\tAddresses: %d\n", ts->pfrts_cnt); 398126353Smlaier printf("\tCleared: %s", ctime(&time)); 399126353Smlaier printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n", 400126353Smlaier ts->pfrts_refcnt[PFR_REFCNT_ANCHOR], 401126353Smlaier ts->pfrts_refcnt[PFR_REFCNT_RULE]); 402127024Smlaier printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n", 403127024Smlaier (unsigned long long)ts->pfrts_nomatch, 404127024Smlaier (unsigned long long)ts->pfrts_match); 405126353Smlaier for (dir = 0; dir < PFR_DIR_MAX; dir++) 406126353Smlaier for (op = 0; op < PFR_OP_TABLE_MAX; op++) 407127024Smlaier printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", 408126353Smlaier stats_text[dir][op], 409127024Smlaier (unsigned long long)ts->pfrts_packets[dir][op], 410127024Smlaier (unsigned long long)ts->pfrts_bytes[dir][op]); 411126353Smlaier} 412126353Smlaier 413126353Smlaierint 414126353Smlaierload_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, 415126353Smlaier int nonetwork) 416126353Smlaier{ 417126353Smlaier while (argc--) 418126353Smlaier if (append_addr(b, *argv++, nonetwork)) { 419126353Smlaier if (errno) 420126353Smlaier warn("cannot decode %s", argv[-1]); 421126353Smlaier return (-1); 422126353Smlaier } 423126353Smlaier if (pfr_buf_load(b, file, nonetwork, append_addr)) { 424126353Smlaier warn("cannot load %s", file); 425126353Smlaier return (-1); 426126353Smlaier } 427126353Smlaier return (0); 428126353Smlaier} 429126353Smlaier 430126353Smlaiervoid 431126353Smlaierprint_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) 432126353Smlaier{ 433126353Smlaier char ch, buf[256] = "{error}"; 434223637Sbz char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y', ' ' }; 435126353Smlaier unsigned int fback, hostnet; 436126353Smlaier 437126353Smlaier fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback; 438126353Smlaier ch = (fback < sizeof(fb)/sizeof(*fb)) ? fb[fback] : '?'; 439126353Smlaier hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32; 440126353Smlaier inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf)); 441126353Smlaier printf("%c %c%s", ch, (ad->pfra_not?'!':' '), buf); 442126353Smlaier if (ad->pfra_net < hostnet) 443126353Smlaier printf("/%d", ad->pfra_net); 444126353Smlaier if (rad != NULL && fback != PFR_FB_NONE) { 445126353Smlaier if (strlcpy(buf, "{error}", sizeof(buf)) >= sizeof(buf)) 446126353Smlaier errx(1, "print_addrx: strlcpy"); 447126353Smlaier inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf)); 448126353Smlaier printf("\t%c%s", (rad->pfra_not?'!':' '), buf); 449126353Smlaier if (rad->pfra_net < hostnet) 450126353Smlaier printf("/%d", rad->pfra_net); 451126353Smlaier } 452126353Smlaier if (rad != NULL && fback == PFR_FB_NONE) 453126353Smlaier printf("\t nomatch"); 454126353Smlaier if (dns && ad->pfra_net == hostnet) { 455126353Smlaier char host[NI_MAXHOST]; 456126353Smlaier union sockaddr_union sa; 457126353Smlaier 458126353Smlaier strlcpy(host, "?", sizeof(host)); 459126353Smlaier bzero(&sa, sizeof(sa)); 460126353Smlaier sa.sa.sa_family = ad->pfra_af; 461126353Smlaier if (sa.sa.sa_family == AF_INET) { 462126353Smlaier sa.sa.sa_len = sizeof(sa.sin); 463126353Smlaier sa.sin.sin_addr = ad->pfra_ip4addr; 464126353Smlaier } else { 465126353Smlaier sa.sa.sa_len = sizeof(sa.sin6); 466126353Smlaier sa.sin6.sin6_addr = ad->pfra_ip6addr; 467126353Smlaier } 468126353Smlaier if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host), 469126353Smlaier NULL, 0, NI_NAMEREQD) == 0) 470126353Smlaier printf("\t(%s)", host); 471126353Smlaier } 472126353Smlaier printf("\n"); 473126353Smlaier} 474126353Smlaier 475126353Smlaiervoid 476126353Smlaierprint_astats(struct pfr_astats *as, int dns) 477126353Smlaier{ 478126353Smlaier time_t time = as->pfras_tzero; 479126353Smlaier int dir, op; 480126353Smlaier 481126353Smlaier print_addrx(&as->pfras_a, NULL, dns); 482126353Smlaier printf("\tCleared: %s", ctime(&time)); 483223637Sbz if (as->pfras_a.pfra_fback == PFR_FB_NOCOUNT) 484223637Sbz return; 485126353Smlaier for (dir = 0; dir < PFR_DIR_MAX; dir++) 486126353Smlaier for (op = 0; op < PFR_OP_ADDR_MAX; op++) 487127024Smlaier printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", 488126353Smlaier stats_text[dir][op], 489127024Smlaier (unsigned long long)as->pfras_packets[dir][op], 490127024Smlaier (unsigned long long)as->pfras_bytes[dir][op]); 491126353Smlaier} 492126353Smlaier 493126353Smlaiervoid 494126353Smlaierradix_perror(void) 495126353Smlaier{ 496126353Smlaier extern char *__progname; 497126353Smlaier fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno)); 498126353Smlaier} 499126353Smlaier 500126353Smlaierint 501126353Smlaierpfctl_define_table(char *name, int flags, int addrs, const char *anchor, 502145840Smlaier struct pfr_buffer *ab, u_int32_t ticket) 503126353Smlaier{ 504126353Smlaier struct pfr_table tbl; 505126353Smlaier 506126353Smlaier bzero(&tbl, sizeof(tbl)); 507130617Smlaier if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >= 508130617Smlaier sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor, 509145840Smlaier sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor)) 510126353Smlaier errx(1, "pfctl_define_table: strlcpy"); 511126353Smlaier tbl.pfrt_flags = flags; 512126353Smlaier 513126353Smlaier return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, 514126353Smlaier NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0); 515126353Smlaier} 516126353Smlaier 517126353Smlaiervoid 518126353Smlaierwarn_namespace_collision(const char *filter) 519126353Smlaier{ 520126353Smlaier struct pfr_buffer b; 521126353Smlaier struct pfr_table *t; 522126353Smlaier const char *name = NULL, *lastcoll; 523126353Smlaier int coll = 0; 524126353Smlaier 525126353Smlaier bzero(&b, sizeof(b)); 526126353Smlaier b.pfrb_type = PFRB_TABLES; 527126353Smlaier for (;;) { 528126353Smlaier pfr_buf_grow(&b, b.pfrb_size); 529126353Smlaier b.pfrb_size = b.pfrb_msize; 530126353Smlaier if (pfr_get_tables(NULL, b.pfrb_caddr, 531126353Smlaier &b.pfrb_size, PFR_FLAG_ALLRSETS)) 532130617Smlaier err(1, "pfr_get_tables"); 533126353Smlaier if (b.pfrb_size <= b.pfrb_msize) 534126353Smlaier break; 535126353Smlaier } 536126353Smlaier PFRB_FOREACH(t, &b) { 537126353Smlaier if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE)) 538126353Smlaier continue; 539126353Smlaier if (filter != NULL && strcmp(filter, t->pfrt_name)) 540126353Smlaier continue; 541126353Smlaier if (!t->pfrt_anchor[0]) 542126353Smlaier name = t->pfrt_name; 543126353Smlaier else if (name != NULL && !strcmp(name, t->pfrt_name)) { 544126353Smlaier coll++; 545126353Smlaier lastcoll = name; 546126353Smlaier name = NULL; 547126353Smlaier } 548126353Smlaier } 549126353Smlaier if (coll == 1) 550126353Smlaier warnx("warning: namespace collision with <%s> global table.", 551126353Smlaier lastcoll); 552126353Smlaier else if (coll > 1) 553126353Smlaier warnx("warning: namespace collisions with %d global tables.", 554126353Smlaier coll); 555126353Smlaier pfr_buf_clear(&b); 556126353Smlaier} 557126353Smlaier 558126353Smlaiervoid 559126353Smlaierxprintf(int opts, const char *fmt, ...) 560126353Smlaier{ 561126353Smlaier va_list args; 562126353Smlaier 563126353Smlaier if (opts & PF_OPT_QUIET) 564126353Smlaier return; 565126353Smlaier 566126353Smlaier va_start(args, fmt); 567126353Smlaier vfprintf(stderr, fmt, args); 568126353Smlaier va_end(args); 569126353Smlaier 570126353Smlaier if (opts & PF_OPT_DUMMYACTION) 571126353Smlaier fprintf(stderr, " (dummy).\n"); 572126353Smlaier else if (opts & PF_OPT_NOACTION) 573126353Smlaier fprintf(stderr, " (syntax only).\n"); 574126353Smlaier else 575126353Smlaier fprintf(stderr, ".\n"); 576126353Smlaier} 577130617Smlaier 578130617Smlaier 579130617Smlaier/* interface stuff */ 580130617Smlaier 581130617Smlaierint 582130617Smlaierpfctl_show_ifaces(const char *filter, int opts) 583130617Smlaier{ 584130617Smlaier struct pfr_buffer b; 585171172Smlaier struct pfi_kif *p; 586171172Smlaier int i = 0; 587130617Smlaier 588130617Smlaier bzero(&b, sizeof(b)); 589130617Smlaier b.pfrb_type = PFRB_IFACES; 590130617Smlaier for (;;) { 591130617Smlaier pfr_buf_grow(&b, b.pfrb_size); 592130617Smlaier b.pfrb_size = b.pfrb_msize; 593171172Smlaier if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) { 594130617Smlaier radix_perror(); 595130617Smlaier return (1); 596130617Smlaier } 597130617Smlaier if (b.pfrb_size <= b.pfrb_msize) 598130617Smlaier break; 599130617Smlaier i++; 600130617Smlaier } 601130617Smlaier if (opts & PF_OPT_SHOWALL) 602130617Smlaier pfctl_print_title("INTERFACES:"); 603130617Smlaier PFRB_FOREACH(p, &b) 604130617Smlaier print_iface(p, opts); 605130617Smlaier return (0); 606130617Smlaier} 607130617Smlaier 608130617Smlaiervoid 609171172Smlaierprint_iface(struct pfi_kif *p, int opts) 610130617Smlaier{ 611171172Smlaier time_t tzero = p->pfik_tzero; 612130617Smlaier int i, af, dir, act; 613130617Smlaier 614171172Smlaier printf("%s", p->pfik_name); 615171172Smlaier if (opts & PF_OPT_VERBOSE) { 616171172Smlaier if (p->pfik_flags & PFI_IFLAG_SKIP) 617171172Smlaier printf(" (skip)"); 618171172Smlaier } 619130617Smlaier printf("\n"); 620130617Smlaier 621130617Smlaier if (!(opts & PF_OPT_VERBOSE2)) 622130617Smlaier return; 623130617Smlaier printf("\tCleared: %s", ctime(&tzero)); 624240233Sglebius printf("\tReferences: %-18d\n", p->pfik_rulerefs); 625130617Smlaier for (i = 0; i < 8; i++) { 626130617Smlaier af = (i>>2) & 1; 627130617Smlaier dir = (i>>1) &1; 628130617Smlaier act = i & 1; 629130617Smlaier printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", 630130617Smlaier istats_text[af][dir][act], 631171172Smlaier (unsigned long long)p->pfik_packets[af][dir][act], 632171172Smlaier (unsigned long long)p->pfik_bytes[af][dir][act]); 633130617Smlaier } 634130617Smlaier} 635