1 1.7 yamt /* $NetBSD: pfctl_table.c,v 1.7 2008/06/18 09:06:26 yamt Exp $ */ 2 1.7 yamt /* $OpenBSD: pfctl_table.c,v 1.66 2007/03/01 17:20:54 deraadt Exp $ */ 3 1.1 itojun 4 1.1 itojun /* 5 1.1 itojun * Copyright (c) 2002 Cedric Berger 6 1.1 itojun * All rights reserved. 7 1.1 itojun * 8 1.1 itojun * Redistribution and use in source and binary forms, with or without 9 1.1 itojun * modification, are permitted provided that the following conditions 10 1.1 itojun * are met: 11 1.1 itojun * 12 1.1 itojun * - Redistributions of source code must retain the above copyright 13 1.1 itojun * notice, this list of conditions and the following disclaimer. 14 1.1 itojun * - Redistributions in binary form must reproduce the above 15 1.1 itojun * copyright notice, this list of conditions and the following 16 1.1 itojun * disclaimer in the documentation and/or other materials provided 17 1.1 itojun * with the distribution. 18 1.1 itojun * 19 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 1.1 itojun * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 1.1 itojun * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 22 1.1 itojun * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 23 1.1 itojun * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 24 1.1 itojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 25 1.1 itojun * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 1.1 itojun * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 1.1 itojun * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 1.1 itojun * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 29 1.1 itojun * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 itojun * POSSIBILITY OF SUCH DAMAGE. 31 1.1 itojun * 32 1.1 itojun */ 33 1.1 itojun 34 1.1 itojun #include <sys/types.h> 35 1.1 itojun #include <sys/ioctl.h> 36 1.1 itojun #include <sys/socket.h> 37 1.1 itojun 38 1.1 itojun #include <net/if.h> 39 1.1 itojun #include <net/pfvar.h> 40 1.1 itojun #include <arpa/inet.h> 41 1.1 itojun 42 1.1 itojun #include <ctype.h> 43 1.1 itojun #include <err.h> 44 1.1 itojun #include <errno.h> 45 1.1 itojun #include <netdb.h> 46 1.1 itojun #include <stdarg.h> 47 1.1 itojun #include <stdio.h> 48 1.1 itojun #include <stdlib.h> 49 1.1 itojun #include <string.h> 50 1.1 itojun #include <time.h> 51 1.1 itojun 52 1.1 itojun #include "pfctl_parser.h" 53 1.1 itojun #include "pfctl.h" 54 1.1 itojun 55 1.1 itojun extern void usage(void); 56 1.1 itojun static int pfctl_table(int, char *[], char *, const char *, char *, 57 1.4 yamt const char *, int); 58 1.1 itojun static void print_table(struct pfr_table *, int, int); 59 1.1 itojun static void print_tstats(struct pfr_tstats *, int); 60 1.1 itojun static int load_addr(struct pfr_buffer *, int, char *[], char *, int); 61 1.1 itojun static void print_addrx(struct pfr_addr *, struct pfr_addr *, int); 62 1.1 itojun static void print_astats(struct pfr_astats *, int); 63 1.1 itojun static void radix_perror(void); 64 1.1 itojun static void xprintf(int, const char *, ...); 65 1.7 yamt static void print_iface(struct pfi_kif *, int); 66 1.1 itojun 67 1.1 itojun static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { 68 1.1 itojun { "In/Block:", "In/Pass:", "In/XPass:" }, 69 1.1 itojun { "Out/Block:", "Out/Pass:", "Out/XPass:" } 70 1.1 itojun }; 71 1.1 itojun 72 1.1 itojun static const char *istats_text[2][2][2] = { 73 1.1 itojun { { "In4/Pass:", "In4/Block:" }, { "Out4/Pass:", "Out4/Block:" } }, 74 1.1 itojun { { "In6/Pass:", "In6/Block:" }, { "Out6/Pass:", "Out6/Block:" } } 75 1.1 itojun }; 76 1.1 itojun 77 1.1 itojun #define RVTEST(fct) do { \ 78 1.1 itojun if ((!(opts & PF_OPT_NOACTION) || \ 79 1.1 itojun (opts & PF_OPT_DUMMYACTION)) && \ 80 1.1 itojun (fct)) { \ 81 1.1 itojun radix_perror(); \ 82 1.1 itojun goto _error; \ 83 1.1 itojun } \ 84 1.1 itojun } while (0) 85 1.1 itojun 86 1.1 itojun #define CREATE_TABLE do { \ 87 1.1 itojun table.pfrt_flags |= PFR_TFLAG_PERSIST; \ 88 1.4 yamt if ((!(opts & PF_OPT_NOACTION) || \ 89 1.4 yamt (opts & PF_OPT_DUMMYACTION)) && \ 90 1.4 yamt (pfr_add_tables(&table, 1, &nadd, flags)) && \ 91 1.4 yamt (errno != EPERM)) { \ 92 1.4 yamt radix_perror(); \ 93 1.4 yamt goto _error; \ 94 1.4 yamt } \ 95 1.1 itojun if (nadd) { \ 96 1.1 itojun warn_namespace_collision(table.pfrt_name); \ 97 1.1 itojun xprintf(opts, "%d table created", nadd); \ 98 1.1 itojun if (opts & PF_OPT_NOACTION) \ 99 1.1 itojun return (0); \ 100 1.1 itojun } \ 101 1.1 itojun table.pfrt_flags &= ~PFR_TFLAG_PERSIST; \ 102 1.1 itojun } while(0) 103 1.1 itojun 104 1.1 itojun int 105 1.4 yamt pfctl_clear_tables(const char *anchor, int opts) 106 1.1 itojun { 107 1.4 yamt return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, opts); 108 1.1 itojun } 109 1.1 itojun 110 1.1 itojun int 111 1.4 yamt pfctl_show_tables(const char *anchor, int opts) 112 1.1 itojun { 113 1.4 yamt return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, opts); 114 1.1 itojun } 115 1.1 itojun 116 1.1 itojun int 117 1.1 itojun pfctl_command_tables(int argc, char *argv[], char *tname, 118 1.4 yamt const char *command, char *file, const char *anchor, int opts) 119 1.1 itojun { 120 1.1 itojun if (tname == NULL || command == NULL) 121 1.1 itojun usage(); 122 1.4 yamt return pfctl_table(argc, argv, tname, command, file, anchor, opts); 123 1.1 itojun } 124 1.1 itojun 125 1.1 itojun int 126 1.1 itojun pfctl_table(int argc, char *argv[], char *tname, const char *command, 127 1.4 yamt char *file, const char *anchor, int opts) 128 1.1 itojun { 129 1.1 itojun struct pfr_table table; 130 1.1 itojun struct pfr_buffer b, b2; 131 1.1 itojun struct pfr_addr *a, *a2; 132 1.1 itojun int nadd = 0, ndel = 0, nchange = 0, nzero = 0; 133 1.1 itojun int rv = 0, flags = 0, nmatch = 0; 134 1.1 itojun void *p; 135 1.1 itojun 136 1.1 itojun if (command == NULL) 137 1.1 itojun usage(); 138 1.1 itojun if (opts & PF_OPT_NOACTION) 139 1.1 itojun flags |= PFR_FLAG_DUMMY; 140 1.1 itojun 141 1.1 itojun bzero(&b, sizeof(b)); 142 1.1 itojun bzero(&b2, sizeof(b2)); 143 1.1 itojun bzero(&table, sizeof(table)); 144 1.1 itojun if (tname != NULL) { 145 1.1 itojun if (strlen(tname) >= PF_TABLE_NAME_SIZE) 146 1.1 itojun usage(); 147 1.1 itojun if (strlcpy(table.pfrt_name, tname, 148 1.1 itojun sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 149 1.1 itojun errx(1, "pfctl_table: strlcpy"); 150 1.1 itojun } 151 1.1 itojun if (strlcpy(table.pfrt_anchor, anchor, 152 1.4 yamt sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor)) 153 1.1 itojun errx(1, "pfctl_table: strlcpy"); 154 1.1 itojun 155 1.1 itojun if (!strcmp(command, "-F")) { 156 1.1 itojun if (argc || file != NULL) 157 1.1 itojun usage(); 158 1.1 itojun RVTEST(pfr_clr_tables(&table, &ndel, flags)); 159 1.1 itojun xprintf(opts, "%d tables deleted", ndel); 160 1.1 itojun } else if (!strcmp(command, "-s")) { 161 1.1 itojun b.pfrb_type = (opts & PF_OPT_VERBOSE2) ? 162 1.1 itojun PFRB_TSTATS : PFRB_TABLES; 163 1.1 itojun if (argc || file != NULL) 164 1.1 itojun usage(); 165 1.1 itojun for (;;) { 166 1.1 itojun pfr_buf_grow(&b, b.pfrb_size); 167 1.1 itojun b.pfrb_size = b.pfrb_msize; 168 1.1 itojun if (opts & PF_OPT_VERBOSE2) 169 1.1 itojun RVTEST(pfr_get_tstats(&table, 170 1.1 itojun b.pfrb_caddr, &b.pfrb_size, flags)); 171 1.1 itojun else 172 1.1 itojun RVTEST(pfr_get_tables(&table, 173 1.1 itojun b.pfrb_caddr, &b.pfrb_size, flags)); 174 1.1 itojun if (b.pfrb_size <= b.pfrb_msize) 175 1.1 itojun break; 176 1.1 itojun } 177 1.1 itojun 178 1.7 yamt if ((opts & PF_OPT_SHOWALL) && b.pfrb_size > 0) 179 1.1 itojun pfctl_print_title("TABLES:"); 180 1.1 itojun 181 1.1 itojun PFRB_FOREACH(p, &b) 182 1.1 itojun if (opts & PF_OPT_VERBOSE2) 183 1.1 itojun print_tstats(p, opts & PF_OPT_DEBUG); 184 1.1 itojun else 185 1.1 itojun print_table(p, opts & PF_OPT_VERBOSE, 186 1.1 itojun opts & PF_OPT_DEBUG); 187 1.1 itojun } else if (!strcmp(command, "kill")) { 188 1.1 itojun if (argc || file != NULL) 189 1.1 itojun usage(); 190 1.1 itojun RVTEST(pfr_del_tables(&table, 1, &ndel, flags)); 191 1.1 itojun xprintf(opts, "%d table deleted", ndel); 192 1.1 itojun } else if (!strcmp(command, "flush")) { 193 1.1 itojun if (argc || file != NULL) 194 1.1 itojun usage(); 195 1.1 itojun RVTEST(pfr_clr_addrs(&table, &ndel, flags)); 196 1.1 itojun xprintf(opts, "%d addresses deleted", ndel); 197 1.1 itojun } else if (!strcmp(command, "add")) { 198 1.1 itojun b.pfrb_type = PFRB_ADDRS; 199 1.1 itojun if (load_addr(&b, argc, argv, file, 0)) 200 1.1 itojun goto _error; 201 1.1 itojun CREATE_TABLE; 202 1.1 itojun if (opts & PF_OPT_VERBOSE) 203 1.1 itojun flags |= PFR_FLAG_FEEDBACK; 204 1.1 itojun RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, 205 1.1 itojun &nadd, flags)); 206 1.1 itojun xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size); 207 1.1 itojun if (opts & PF_OPT_VERBOSE) 208 1.1 itojun PFRB_FOREACH(a, &b) 209 1.1 itojun if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 210 1.1 itojun print_addrx(a, NULL, 211 1.1 itojun opts & PF_OPT_USEDNS); 212 1.1 itojun } else if (!strcmp(command, "delete")) { 213 1.1 itojun b.pfrb_type = PFRB_ADDRS; 214 1.1 itojun if (load_addr(&b, argc, argv, file, 0)) 215 1.1 itojun goto _error; 216 1.1 itojun if (opts & PF_OPT_VERBOSE) 217 1.1 itojun flags |= PFR_FLAG_FEEDBACK; 218 1.1 itojun RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size, 219 1.1 itojun &ndel, flags)); 220 1.1 itojun xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size); 221 1.1 itojun if (opts & PF_OPT_VERBOSE) 222 1.1 itojun PFRB_FOREACH(a, &b) 223 1.1 itojun if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 224 1.1 itojun print_addrx(a, NULL, 225 1.1 itojun opts & PF_OPT_USEDNS); 226 1.1 itojun } else if (!strcmp(command, "replace")) { 227 1.1 itojun b.pfrb_type = PFRB_ADDRS; 228 1.1 itojun if (load_addr(&b, argc, argv, file, 0)) 229 1.1 itojun goto _error; 230 1.1 itojun CREATE_TABLE; 231 1.1 itojun if (opts & PF_OPT_VERBOSE) 232 1.1 itojun flags |= PFR_FLAG_FEEDBACK; 233 1.1 itojun for (;;) { 234 1.1 itojun int sz2 = b.pfrb_msize; 235 1.1 itojun 236 1.1 itojun RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size, 237 1.1 itojun &sz2, &nadd, &ndel, &nchange, flags)); 238 1.1 itojun if (sz2 <= b.pfrb_msize) { 239 1.1 itojun b.pfrb_size = sz2; 240 1.1 itojun break; 241 1.1 itojun } else 242 1.1 itojun pfr_buf_grow(&b, sz2); 243 1.1 itojun } 244 1.1 itojun if (nadd) 245 1.1 itojun xprintf(opts, "%d addresses added", nadd); 246 1.1 itojun if (ndel) 247 1.1 itojun xprintf(opts, "%d addresses deleted", ndel); 248 1.1 itojun if (nchange) 249 1.1 itojun xprintf(opts, "%d addresses changed", nchange); 250 1.1 itojun if (!nadd && !ndel && !nchange) 251 1.1 itojun xprintf(opts, "no changes"); 252 1.1 itojun if (opts & PF_OPT_VERBOSE) 253 1.1 itojun PFRB_FOREACH(a, &b) 254 1.1 itojun if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 255 1.1 itojun print_addrx(a, NULL, 256 1.1 itojun opts & PF_OPT_USEDNS); 257 1.7 yamt } else if (!strcmp(command, "expire")) { 258 1.7 yamt const char *errstr = NULL; /* XXX gcc */ 259 1.7 yamt u_int lifetime; 260 1.7 yamt 261 1.7 yamt b.pfrb_type = PFRB_ASTATS; 262 1.7 yamt b2.pfrb_type = PFRB_ADDRS; 263 1.7 yamt if (argc != 1 || file != NULL) 264 1.7 yamt usage(); 265 1.7 yamt lifetime = strtonum(*argv, 0, UINT_MAX, &errstr); 266 1.7 yamt if (errstr) 267 1.7 yamt errx(1, "expiry time: %s", errstr); 268 1.7 yamt for (;;) { 269 1.7 yamt pfr_buf_grow(&b, b.pfrb_size); 270 1.7 yamt b.pfrb_size = b.pfrb_msize; 271 1.7 yamt RVTEST(pfr_get_astats(&table, b.pfrb_caddr, 272 1.7 yamt &b.pfrb_size, flags)); 273 1.7 yamt if (b.pfrb_size <= b.pfrb_msize) 274 1.7 yamt break; 275 1.7 yamt } 276 1.7 yamt PFRB_FOREACH(p, &b) 277 1.7 yamt if (time(NULL) - ((struct pfr_astats *)p)->pfras_tzero > 278 1.7 yamt lifetime) 279 1.7 yamt if (pfr_buf_add(&b2, 280 1.7 yamt &((struct pfr_astats *)p)->pfras_a)) 281 1.7 yamt err(1, "duplicate buffer"); 282 1.7 yamt 283 1.7 yamt if (opts & PF_OPT_VERBOSE) 284 1.7 yamt flags |= PFR_FLAG_FEEDBACK; 285 1.7 yamt RVTEST(pfr_del_addrs(&table, b2.pfrb_caddr, b2.pfrb_size, 286 1.7 yamt &ndel, flags)); 287 1.7 yamt xprintf(opts, "%d/%d addresses expired", ndel, b2.pfrb_size); 288 1.7 yamt if (opts & PF_OPT_VERBOSE) 289 1.7 yamt PFRB_FOREACH(a, &b2) 290 1.7 yamt if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 291 1.7 yamt print_addrx(a, NULL, 292 1.7 yamt opts & PF_OPT_USEDNS); 293 1.1 itojun } else if (!strcmp(command, "show")) { 294 1.1 itojun b.pfrb_type = (opts & PF_OPT_VERBOSE) ? 295 1.1 itojun PFRB_ASTATS : PFRB_ADDRS; 296 1.1 itojun if (argc || file != NULL) 297 1.1 itojun usage(); 298 1.1 itojun for (;;) { 299 1.1 itojun pfr_buf_grow(&b, b.pfrb_size); 300 1.1 itojun b.pfrb_size = b.pfrb_msize; 301 1.1 itojun if (opts & PF_OPT_VERBOSE) 302 1.1 itojun RVTEST(pfr_get_astats(&table, b.pfrb_caddr, 303 1.1 itojun &b.pfrb_size, flags)); 304 1.1 itojun else 305 1.1 itojun RVTEST(pfr_get_addrs(&table, b.pfrb_caddr, 306 1.1 itojun &b.pfrb_size, flags)); 307 1.1 itojun if (b.pfrb_size <= b.pfrb_msize) 308 1.1 itojun break; 309 1.1 itojun } 310 1.1 itojun PFRB_FOREACH(p, &b) 311 1.1 itojun if (opts & PF_OPT_VERBOSE) 312 1.1 itojun print_astats(p, opts & PF_OPT_USEDNS); 313 1.1 itojun else 314 1.1 itojun print_addrx(p, NULL, opts & PF_OPT_USEDNS); 315 1.1 itojun } else if (!strcmp(command, "test")) { 316 1.1 itojun b.pfrb_type = PFRB_ADDRS; 317 1.1 itojun b2.pfrb_type = PFRB_ADDRS; 318 1.1 itojun 319 1.1 itojun if (load_addr(&b, argc, argv, file, 1)) 320 1.1 itojun goto _error; 321 1.1 itojun if (opts & PF_OPT_VERBOSE2) { 322 1.1 itojun flags |= PFR_FLAG_REPLACE; 323 1.1 itojun PFRB_FOREACH(a, &b) 324 1.1 itojun if (pfr_buf_add(&b2, a)) 325 1.1 itojun err(1, "duplicate buffer"); 326 1.1 itojun } 327 1.1 itojun RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size, 328 1.1 itojun &nmatch, flags)); 329 1.1 itojun xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size); 330 1.7 yamt if ((opts & PF_OPT_VERBOSE) && !(opts & PF_OPT_VERBOSE2)) 331 1.1 itojun PFRB_FOREACH(a, &b) 332 1.1 itojun if (a->pfra_fback == PFR_FB_MATCH) 333 1.1 itojun print_addrx(a, NULL, 334 1.1 itojun opts & PF_OPT_USEDNS); 335 1.1 itojun if (opts & PF_OPT_VERBOSE2) { 336 1.1 itojun a2 = NULL; 337 1.1 itojun PFRB_FOREACH(a, &b) { 338 1.1 itojun a2 = pfr_buf_next(&b2, a2); 339 1.1 itojun print_addrx(a2, a, opts & PF_OPT_USEDNS); 340 1.1 itojun } 341 1.1 itojun } 342 1.1 itojun if (nmatch < b.pfrb_size) 343 1.1 itojun rv = 2; 344 1.1 itojun } else if (!strcmp(command, "zero")) { 345 1.1 itojun if (argc || file != NULL) 346 1.1 itojun usage(); 347 1.1 itojun flags |= PFR_FLAG_ADDRSTOO; 348 1.1 itojun RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags)); 349 1.1 itojun xprintf(opts, "%d table/stats cleared", nzero); 350 1.1 itojun } else 351 1.1 itojun warnx("pfctl_table: unknown command '%s'", command); 352 1.1 itojun goto _cleanup; 353 1.1 itojun 354 1.1 itojun _error: 355 1.1 itojun rv = -1; 356 1.1 itojun _cleanup: 357 1.1 itojun pfr_buf_clear(&b); 358 1.1 itojun pfr_buf_clear(&b2); 359 1.1 itojun return (rv); 360 1.1 itojun } 361 1.1 itojun 362 1.1 itojun void 363 1.1 itojun print_table(struct pfr_table *ta, int verbose, int debug) 364 1.1 itojun { 365 1.1 itojun if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE)) 366 1.1 itojun return; 367 1.1 itojun if (verbose) { 368 1.1 itojun printf("%c%c%c%c%c%c\t%s", 369 1.1 itojun (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-', 370 1.1 itojun (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-', 371 1.1 itojun (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-', 372 1.1 itojun (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-', 373 1.1 itojun (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-', 374 1.1 itojun (ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-', 375 1.1 itojun ta->pfrt_name); 376 1.1 itojun if (ta->pfrt_anchor[0]) 377 1.1 itojun printf("\t%s", ta->pfrt_anchor); 378 1.1 itojun puts(""); 379 1.1 itojun } else 380 1.1 itojun puts(ta->pfrt_name); 381 1.1 itojun } 382 1.1 itojun 383 1.1 itojun void 384 1.1 itojun print_tstats(struct pfr_tstats *ts, int debug) 385 1.1 itojun { 386 1.1 itojun time_t time = ts->pfrts_tzero; 387 1.1 itojun int dir, op; 388 1.1 itojun 389 1.1 itojun if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) 390 1.1 itojun return; 391 1.1 itojun print_table(&ts->pfrts_t, 1, debug); 392 1.1 itojun printf("\tAddresses: %d\n", ts->pfrts_cnt); 393 1.1 itojun printf("\tCleared: %s", ctime(&time)); 394 1.1 itojun printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n", 395 1.1 itojun ts->pfrts_refcnt[PFR_REFCNT_ANCHOR], 396 1.1 itojun ts->pfrts_refcnt[PFR_REFCNT_RULE]); 397 1.1 itojun printf("\tEvaluations: [ NoMatch: %-18llu Match: %-18llu ]\n", 398 1.1 itojun (unsigned long long)ts->pfrts_nomatch, 399 1.1 itojun (unsigned long long)ts->pfrts_match); 400 1.1 itojun for (dir = 0; dir < PFR_DIR_MAX; dir++) 401 1.1 itojun for (op = 0; op < PFR_OP_TABLE_MAX; op++) 402 1.1 itojun printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", 403 1.1 itojun stats_text[dir][op], 404 1.1 itojun (unsigned long long)ts->pfrts_packets[dir][op], 405 1.1 itojun (unsigned long long)ts->pfrts_bytes[dir][op]); 406 1.1 itojun } 407 1.1 itojun 408 1.1 itojun int 409 1.1 itojun load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, 410 1.1 itojun int nonetwork) 411 1.1 itojun { 412 1.1 itojun while (argc--) 413 1.1 itojun if (append_addr(b, *argv++, nonetwork)) { 414 1.1 itojun if (errno) 415 1.1 itojun warn("cannot decode %s", argv[-1]); 416 1.1 itojun return (-1); 417 1.1 itojun } 418 1.1 itojun if (pfr_buf_load(b, file, nonetwork, append_addr)) { 419 1.1 itojun warn("cannot load %s", file); 420 1.1 itojun return (-1); 421 1.1 itojun } 422 1.1 itojun return (0); 423 1.1 itojun } 424 1.1 itojun 425 1.1 itojun void 426 1.1 itojun print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) 427 1.1 itojun { 428 1.1 itojun char ch, buf[256] = "{error}"; 429 1.1 itojun char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' }; 430 1.1 itojun unsigned int fback, hostnet; 431 1.1 itojun 432 1.1 itojun fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback; 433 1.1 itojun ch = (fback < sizeof(fb)/sizeof(*fb)) ? fb[fback] : '?'; 434 1.1 itojun hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32; 435 1.1 itojun inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf)); 436 1.1 itojun printf("%c %c%s", ch, (ad->pfra_not?'!':' '), buf); 437 1.1 itojun if (ad->pfra_net < hostnet) 438 1.1 itojun printf("/%d", ad->pfra_net); 439 1.1 itojun if (rad != NULL && fback != PFR_FB_NONE) { 440 1.1 itojun if (strlcpy(buf, "{error}", sizeof(buf)) >= sizeof(buf)) 441 1.1 itojun errx(1, "print_addrx: strlcpy"); 442 1.1 itojun inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf)); 443 1.1 itojun printf("\t%c%s", (rad->pfra_not?'!':' '), buf); 444 1.1 itojun if (rad->pfra_net < hostnet) 445 1.1 itojun printf("/%d", rad->pfra_net); 446 1.1 itojun } 447 1.1 itojun if (rad != NULL && fback == PFR_FB_NONE) 448 1.1 itojun printf("\t nomatch"); 449 1.1 itojun if (dns && ad->pfra_net == hostnet) { 450 1.1 itojun char host[NI_MAXHOST]; 451 1.1 itojun union sockaddr_union sa; 452 1.1 itojun 453 1.1 itojun strlcpy(host, "?", sizeof(host)); 454 1.1 itojun bzero(&sa, sizeof(sa)); 455 1.1 itojun sa.sa.sa_family = ad->pfra_af; 456 1.1 itojun if (sa.sa.sa_family == AF_INET) { 457 1.1 itojun sa.sa.sa_len = sizeof(sa.sin); 458 1.1 itojun sa.sin.sin_addr = ad->pfra_ip4addr; 459 1.1 itojun } else { 460 1.1 itojun sa.sa.sa_len = sizeof(sa.sin6); 461 1.1 itojun sa.sin6.sin6_addr = ad->pfra_ip6addr; 462 1.1 itojun } 463 1.1 itojun if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host), 464 1.1 itojun NULL, 0, NI_NAMEREQD) == 0) 465 1.1 itojun printf("\t(%s)", host); 466 1.1 itojun } 467 1.1 itojun printf("\n"); 468 1.1 itojun } 469 1.1 itojun 470 1.1 itojun void 471 1.1 itojun print_astats(struct pfr_astats *as, int dns) 472 1.1 itojun { 473 1.1 itojun time_t time = as->pfras_tzero; 474 1.1 itojun int dir, op; 475 1.1 itojun 476 1.1 itojun print_addrx(&as->pfras_a, NULL, dns); 477 1.1 itojun printf("\tCleared: %s", ctime(&time)); 478 1.1 itojun for (dir = 0; dir < PFR_DIR_MAX; dir++) 479 1.1 itojun for (op = 0; op < PFR_OP_ADDR_MAX; op++) 480 1.1 itojun printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", 481 1.1 itojun stats_text[dir][op], 482 1.1 itojun (unsigned long long)as->pfras_packets[dir][op], 483 1.1 itojun (unsigned long long)as->pfras_bytes[dir][op]); 484 1.1 itojun } 485 1.1 itojun 486 1.1 itojun void 487 1.1 itojun radix_perror(void) 488 1.1 itojun { 489 1.1 itojun extern char *__progname; 490 1.1 itojun fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno)); 491 1.1 itojun } 492 1.1 itojun 493 1.1 itojun int 494 1.1 itojun pfctl_define_table(char *name, int flags, int addrs, const char *anchor, 495 1.4 yamt struct pfr_buffer *ab, u_int32_t ticket) 496 1.1 itojun { 497 1.1 itojun struct pfr_table tbl; 498 1.1 itojun 499 1.1 itojun bzero(&tbl, sizeof(tbl)); 500 1.1 itojun if (strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)) >= 501 1.1 itojun sizeof(tbl.pfrt_name) || strlcpy(tbl.pfrt_anchor, anchor, 502 1.4 yamt sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor)) 503 1.1 itojun errx(1, "pfctl_define_table: strlcpy"); 504 1.1 itojun tbl.pfrt_flags = flags; 505 1.1 itojun 506 1.1 itojun return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, 507 1.1 itojun NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0); 508 1.1 itojun } 509 1.1 itojun 510 1.1 itojun void 511 1.1 itojun warn_namespace_collision(const char *filter) 512 1.1 itojun { 513 1.1 itojun struct pfr_buffer b; 514 1.1 itojun struct pfr_table *t; 515 1.5 lukem const char *name = NULL, *lastcoll = NULL; 516 1.1 itojun int coll = 0; 517 1.1 itojun 518 1.1 itojun bzero(&b, sizeof(b)); 519 1.1 itojun b.pfrb_type = PFRB_TABLES; 520 1.1 itojun for (;;) { 521 1.1 itojun pfr_buf_grow(&b, b.pfrb_size); 522 1.1 itojun b.pfrb_size = b.pfrb_msize; 523 1.1 itojun if (pfr_get_tables(NULL, b.pfrb_caddr, 524 1.1 itojun &b.pfrb_size, PFR_FLAG_ALLRSETS)) 525 1.1 itojun err(1, "pfr_get_tables"); 526 1.1 itojun if (b.pfrb_size <= b.pfrb_msize) 527 1.1 itojun break; 528 1.1 itojun } 529 1.1 itojun PFRB_FOREACH(t, &b) { 530 1.1 itojun if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE)) 531 1.1 itojun continue; 532 1.1 itojun if (filter != NULL && strcmp(filter, t->pfrt_name)) 533 1.1 itojun continue; 534 1.1 itojun if (!t->pfrt_anchor[0]) 535 1.1 itojun name = t->pfrt_name; 536 1.1 itojun else if (name != NULL && !strcmp(name, t->pfrt_name)) { 537 1.1 itojun coll++; 538 1.1 itojun lastcoll = name; 539 1.1 itojun name = NULL; 540 1.1 itojun } 541 1.1 itojun } 542 1.1 itojun if (coll == 1) 543 1.1 itojun warnx("warning: namespace collision with <%s> global table.", 544 1.1 itojun lastcoll); 545 1.1 itojun else if (coll > 1) 546 1.1 itojun warnx("warning: namespace collisions with %d global tables.", 547 1.1 itojun coll); 548 1.1 itojun pfr_buf_clear(&b); 549 1.1 itojun } 550 1.1 itojun 551 1.1 itojun void 552 1.1 itojun xprintf(int opts, const char *fmt, ...) 553 1.1 itojun { 554 1.1 itojun va_list args; 555 1.1 itojun 556 1.1 itojun if (opts & PF_OPT_QUIET) 557 1.1 itojun return; 558 1.1 itojun 559 1.1 itojun va_start(args, fmt); 560 1.1 itojun vfprintf(stderr, fmt, args); 561 1.1 itojun va_end(args); 562 1.1 itojun 563 1.1 itojun if (opts & PF_OPT_DUMMYACTION) 564 1.1 itojun fprintf(stderr, " (dummy).\n"); 565 1.1 itojun else if (opts & PF_OPT_NOACTION) 566 1.1 itojun fprintf(stderr, " (syntax only).\n"); 567 1.1 itojun else 568 1.1 itojun fprintf(stderr, ".\n"); 569 1.1 itojun } 570 1.1 itojun 571 1.1 itojun 572 1.1 itojun /* interface stuff */ 573 1.1 itojun 574 1.1 itojun int 575 1.1 itojun pfctl_show_ifaces(const char *filter, int opts) 576 1.1 itojun { 577 1.1 itojun struct pfr_buffer b; 578 1.7 yamt struct pfi_kif *p; 579 1.7 yamt int i = 0; 580 1.1 itojun 581 1.1 itojun bzero(&b, sizeof(b)); 582 1.1 itojun b.pfrb_type = PFRB_IFACES; 583 1.1 itojun for (;;) { 584 1.1 itojun pfr_buf_grow(&b, b.pfrb_size); 585 1.1 itojun b.pfrb_size = b.pfrb_msize; 586 1.7 yamt if (pfi_get_ifaces(filter, b.pfrb_caddr, &b.pfrb_size)) { 587 1.1 itojun radix_perror(); 588 1.1 itojun return (1); 589 1.1 itojun } 590 1.1 itojun if (b.pfrb_size <= b.pfrb_msize) 591 1.1 itojun break; 592 1.1 itojun i++; 593 1.1 itojun } 594 1.1 itojun if (opts & PF_OPT_SHOWALL) 595 1.1 itojun pfctl_print_title("INTERFACES:"); 596 1.1 itojun PFRB_FOREACH(p, &b) 597 1.1 itojun print_iface(p, opts); 598 1.1 itojun return (0); 599 1.1 itojun } 600 1.1 itojun 601 1.1 itojun void 602 1.7 yamt print_iface(struct pfi_kif *p, int opts) 603 1.1 itojun { 604 1.7 yamt time_t tzero = p->pfik_tzero; 605 1.1 itojun int i, af, dir, act; 606 1.1 itojun 607 1.7 yamt printf("%s", p->pfik_name); 608 1.7 yamt if (opts & PF_OPT_VERBOSE) { 609 1.7 yamt if (p->pfik_flags & PFI_IFLAG_SKIP) 610 1.7 yamt printf(" (skip)"); 611 1.7 yamt } 612 1.1 itojun printf("\n"); 613 1.1 itojun 614 1.1 itojun if (!(opts & PF_OPT_VERBOSE2)) 615 1.1 itojun return; 616 1.1 itojun printf("\tCleared: %s", ctime(&tzero)); 617 1.1 itojun printf("\tReferences: [ States: %-18d Rules: %-18d ]\n", 618 1.7 yamt p->pfik_states, p->pfik_rules); 619 1.1 itojun for (i = 0; i < 8; i++) { 620 1.1 itojun af = (i>>2) & 1; 621 1.1 itojun dir = (i>>1) &1; 622 1.1 itojun act = i & 1; 623 1.1 itojun printf("\t%-12s [ Packets: %-18llu Bytes: %-18llu ]\n", 624 1.1 itojun istats_text[af][dir][act], 625 1.7 yamt (unsigned long long)p->pfik_packets[af][dir][act], 626 1.7 yamt (unsigned long long)p->pfik_bytes[af][dir][act]); 627 1.1 itojun } 628 1.1 itojun } 629