51#include "pfctl_parser.h" 52#include "pfctl.h" 53 54extern void usage(void); 55static int pfctl_table(int, char *[], char *, const char *, char *, 56 const char *, const char *, int); 57static void print_table(struct pfr_table *, int, int); 58static void print_tstats(struct pfr_tstats *, int); 59static int load_addr(struct pfr_buffer *, int, char *[], char *, int); 60static void print_addrx(struct pfr_addr *, struct pfr_addr *, int); 61static void print_astats(struct pfr_astats *, int); 62static void radix_perror(void); 63static void xprintf(int, const char *, ...); 64 65static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { 66 { "In/Block:", "In/Pass:", "In/XPass:" }, 67 { "Out/Block:", "Out/Pass:", "Out/XPass:" } 68}; 69 70#define RVTEST(fct) do { \ 71 if ((!(opts & PF_OPT_NOACTION) || \ 72 (opts & PF_OPT_DUMMYACTION)) && \ 73 (fct)) { \ 74 radix_perror(); \ 75 goto _error; \ 76 } \ 77 } while (0) 78 79#define CREATE_TABLE do { \ 80 table.pfrt_flags |= PFR_TFLAG_PERSIST; \ 81 RVTEST(pfr_add_tables(&table, 1, &nadd, flags)); \ 82 if (nadd) { \ 83 warn_namespace_collision(table.pfrt_name); \ 84 xprintf(opts, "%d table created", nadd); \ 85 if (opts & PF_OPT_NOACTION) \ 86 return (0); \ 87 } \ 88 table.pfrt_flags &= ~PFR_TFLAG_PERSIST; \ 89 } while(0) 90 91int 92pfctl_clear_tables(const char *anchor, const char *ruleset, int opts) 93{ 94 return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts); 95} 96 97int 98pfctl_show_tables(const char *anchor, const char *ruleset, int opts) 99{ 100 return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts); 101} 102 103int 104pfctl_command_tables(int argc, char *argv[], char *tname, 105 const char *command, char *file, const char *anchor, const char *ruleset, 106 int opts) 107{ 108 if (tname == NULL || command == NULL) 109 usage(); 110 return pfctl_table(argc, argv, tname, command, file, anchor, ruleset, 111 opts); 112} 113 114int 115pfctl_table(int argc, char *argv[], char *tname, const char *command, 116 char *file, const char *anchor, const char *ruleset, int opts) 117{ 118 struct pfr_table table; 119 struct pfr_buffer b, b2; 120 struct pfr_addr *a, *a2; 121 int nadd = 0, ndel = 0, nchange = 0, nzero = 0; 122 int rv = 0, flags = 0, nmatch = 0; 123 void *p; 124 125 if (command == NULL) 126 usage(); 127 if (opts & PF_OPT_NOACTION) 128 flags |= PFR_FLAG_DUMMY; 129 130 bzero(&b, sizeof(b)); 131 bzero(&b2, sizeof(b2)); 132 bzero(&table, sizeof(table)); 133 if (tname != NULL) { 134 if (strlen(tname) >= PF_TABLE_NAME_SIZE) 135 usage(); 136 if (strlcpy(table.pfrt_name, tname, 137 sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 138 errx(1, "pfctl_table: strlcpy"); 139 } 140 if (strlcpy(table.pfrt_anchor, anchor, 141 sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) || 142 strlcpy(table.pfrt_ruleset, ruleset, 143 sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset)) 144 errx(1, "pfctl_table: strlcpy"); 145 146 if (!strcmp(command, "-F")) { 147 if (argc || file != NULL) 148 usage(); 149 RVTEST(pfr_clr_tables(&table, &ndel, flags)); 150 xprintf(opts, "%d tables deleted", ndel); 151 } else if (!strcmp(command, "-s")) { 152 b.pfrb_type = (opts & PF_OPT_VERBOSE2) ? 153 PFRB_TSTATS : PFRB_TABLES; 154 if (argc || file != NULL) 155 usage(); 156 for (;;) { 157 pfr_buf_grow(&b, b.pfrb_size); 158 b.pfrb_size = b.pfrb_msize; 159 if (opts & PF_OPT_VERBOSE2) 160 RVTEST(pfr_get_tstats(&table, 161 b.pfrb_caddr, &b.pfrb_size, flags)); 162 else 163 RVTEST(pfr_get_tables(&table, 164 b.pfrb_caddr, &b.pfrb_size, flags)); 165 if (b.pfrb_size <= b.pfrb_msize) 166 break; 167 } 168 PFRB_FOREACH(p, &b) 169 if (opts & PF_OPT_VERBOSE2) 170 print_tstats(p, opts & PF_OPT_DEBUG); 171 else 172 print_table(p, opts & PF_OPT_VERBOSE, 173 opts & PF_OPT_DEBUG); 174 } else if (!strcmp(command, "kill")) { 175 if (argc || file != NULL) 176 usage(); 177 RVTEST(pfr_del_tables(&table, 1, &ndel, flags)); 178 xprintf(opts, "%d table deleted", ndel); 179 } else if (!strcmp(command, "flush")) { 180 if (argc || file != NULL) 181 usage(); 182 RVTEST(pfr_clr_addrs(&table, &ndel, flags)); 183 xprintf(opts, "%d addresses deleted", ndel); 184 } else if (!strcmp(command, "add")) { 185 b.pfrb_type = PFRB_ADDRS; 186 if (load_addr(&b, argc, argv, file, 0)) 187 goto _error; 188 CREATE_TABLE; 189 if (opts & PF_OPT_VERBOSE) 190 flags |= PFR_FLAG_FEEDBACK; 191 RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, 192 &nadd, flags)); 193 xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size); 194 if (opts & PF_OPT_VERBOSE) 195 PFRB_FOREACH(a, &b) 196 if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 197 print_addrx(a, NULL, 198 opts & PF_OPT_USEDNS); 199 } else if (!strcmp(command, "delete")) { 200 b.pfrb_type = PFRB_ADDRS; 201 if (load_addr(&b, argc, argv, file, 0)) 202 goto _error; 203 if (opts & PF_OPT_VERBOSE) 204 flags |= PFR_FLAG_FEEDBACK; 205 RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size, 206 &ndel, flags)); 207 xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size); 208 if (opts & PF_OPT_VERBOSE) 209 PFRB_FOREACH(a, &b) 210 if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 211 print_addrx(a, NULL, 212 opts & PF_OPT_USEDNS); 213 } else if (!strcmp(command, "replace")) { 214 b.pfrb_type = PFRB_ADDRS; 215 if (load_addr(&b, argc, argv, file, 0)) 216 goto _error; 217 CREATE_TABLE; 218 if (opts & PF_OPT_VERBOSE) 219 flags |= PFR_FLAG_FEEDBACK; 220 for (;;) { 221 int sz2 = b.pfrb_msize; 222 223 RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size, 224 &sz2, &nadd, &ndel, &nchange, flags)); 225 if (sz2 <= b.pfrb_msize) { 226 b.pfrb_size = sz2; 227 break; 228 } else 229 pfr_buf_grow(&b, sz2); 230 } 231 if (nadd) 232 xprintf(opts, "%d addresses added", nadd); 233 if (ndel) 234 xprintf(opts, "%d addresses deleted", ndel); 235 if (nchange) 236 xprintf(opts, "%d addresses changed", nchange); 237 if (!nadd && !ndel && !nchange) 238 xprintf(opts, "no changes"); 239 if (opts & PF_OPT_VERBOSE) 240 PFRB_FOREACH(a, &b) 241 if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 242 print_addrx(a, NULL, 243 opts & PF_OPT_USEDNS); 244 } else if (!strcmp(command, "show")) { 245 b.pfrb_type = (opts & PF_OPT_VERBOSE) ? 246 PFRB_ASTATS : PFRB_ADDRS; 247 if (argc || file != NULL) 248 usage(); 249 for (;;) { 250 pfr_buf_grow(&b, b.pfrb_size); 251 b.pfrb_size = b.pfrb_msize; 252 if (opts & PF_OPT_VERBOSE) 253 RVTEST(pfr_get_astats(&table, b.pfrb_caddr, 254 &b.pfrb_size, flags)); 255 else 256 RVTEST(pfr_get_addrs(&table, b.pfrb_caddr, 257 &b.pfrb_size, flags)); 258 if (b.pfrb_size <= b.pfrb_msize) 259 break; 260 } 261 PFRB_FOREACH(p, &b) 262 if (opts & PF_OPT_VERBOSE) 263 print_astats(p, opts & PF_OPT_USEDNS); 264 else 265 print_addrx(p, NULL, opts & PF_OPT_USEDNS); 266 } else if (!strcmp(command, "test")) { 267 b.pfrb_type = PFRB_ADDRS; 268 b2.pfrb_type = PFRB_ADDRS; 269 270 if (load_addr(&b, argc, argv, file, 1)) 271 goto _error; 272 if (opts & PF_OPT_VERBOSE2) { 273 flags |= PFR_FLAG_REPLACE; 274 PFRB_FOREACH(a, &b) 275 if (pfr_buf_add(&b2, a)) 276 err(1, "duplicate buffer"); 277 } 278 RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size, 279 &nmatch, flags)); 280 xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size); 281 if (opts & PF_OPT_VERBOSE && !(opts & PF_OPT_VERBOSE2)) 282 PFRB_FOREACH(a, &b) 283 if (a->pfra_fback == PFR_FB_MATCH) 284 print_addrx(a, NULL, 285 opts & PF_OPT_USEDNS); 286 if (opts & PF_OPT_VERBOSE2) { 287 a2 = NULL; 288 PFRB_FOREACH(a, &b) { 289 a2 = pfr_buf_next(&b2, a2); 290 print_addrx(a2, a, opts & PF_OPT_USEDNS); 291 } 292 } 293 if (nmatch < b.pfrb_size) 294 rv = 2; 295 } else if (!strcmp(command, "zero")) { 296 if (argc || file != NULL) 297 usage(); 298 flags |= PFR_FLAG_ADDRSTOO; 299 RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags)); 300 xprintf(opts, "%d table/stats cleared", nzero); 301 } else 302 warnx("pfctl_table: unknown command '%s'", command); 303 goto _cleanup; 304 305_error: 306 rv = -1; 307_cleanup: 308 pfr_buf_clear(&b); 309 pfr_buf_clear(&b2); 310 return (rv); 311} 312 313void 314print_table(struct pfr_table *ta, int verbose, int debug) 315{ 316 if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE)) 317 return; 318 if (verbose) { 319 printf("%c%c%c%c%c%c\t%s", 320 (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-', 321 (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-', 322 (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-', 323 (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-', 324 (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-', 325 (ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-', 326 ta->pfrt_name); 327 if (ta->pfrt_anchor[0]) 328 printf("\t%s", ta->pfrt_anchor); 329 if (ta->pfrt_ruleset[0]) 330 printf(":%s", ta->pfrt_ruleset); 331 puts(""); 332 } else 333 puts(ta->pfrt_name); 334} 335 336void 337print_tstats(struct pfr_tstats *ts, int debug) 338{ 339 time_t time = ts->pfrts_tzero; 340 int dir, op; 341 342 if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) 343 return; 344 print_table(&ts->pfrts_t, 1, debug); 345 printf("\tAddresses: %d\n", ts->pfrts_cnt); 346 printf("\tCleared: %s", ctime(&time)); 347 printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n", 348 ts->pfrts_refcnt[PFR_REFCNT_ANCHOR], 349 ts->pfrts_refcnt[PFR_REFCNT_RULE]);
| 58#include "pfctl_parser.h" 59#include "pfctl.h" 60 61extern void usage(void); 62static int pfctl_table(int, char *[], char *, const char *, char *, 63 const char *, const char *, int); 64static void print_table(struct pfr_table *, int, int); 65static void print_tstats(struct pfr_tstats *, int); 66static int load_addr(struct pfr_buffer *, int, char *[], char *, int); 67static void print_addrx(struct pfr_addr *, struct pfr_addr *, int); 68static void print_astats(struct pfr_astats *, int); 69static void radix_perror(void); 70static void xprintf(int, const char *, ...); 71 72static const char *stats_text[PFR_DIR_MAX][PFR_OP_TABLE_MAX] = { 73 { "In/Block:", "In/Pass:", "In/XPass:" }, 74 { "Out/Block:", "Out/Pass:", "Out/XPass:" } 75}; 76 77#define RVTEST(fct) do { \ 78 if ((!(opts & PF_OPT_NOACTION) || \ 79 (opts & PF_OPT_DUMMYACTION)) && \ 80 (fct)) { \ 81 radix_perror(); \ 82 goto _error; \ 83 } \ 84 } while (0) 85 86#define CREATE_TABLE do { \ 87 table.pfrt_flags |= PFR_TFLAG_PERSIST; \ 88 RVTEST(pfr_add_tables(&table, 1, &nadd, flags)); \ 89 if (nadd) { \ 90 warn_namespace_collision(table.pfrt_name); \ 91 xprintf(opts, "%d table created", nadd); \ 92 if (opts & PF_OPT_NOACTION) \ 93 return (0); \ 94 } \ 95 table.pfrt_flags &= ~PFR_TFLAG_PERSIST; \ 96 } while(0) 97 98int 99pfctl_clear_tables(const char *anchor, const char *ruleset, int opts) 100{ 101 return pfctl_table(0, NULL, NULL, "-F", NULL, anchor, ruleset, opts); 102} 103 104int 105pfctl_show_tables(const char *anchor, const char *ruleset, int opts) 106{ 107 return pfctl_table(0, NULL, NULL, "-s", NULL, anchor, ruleset, opts); 108} 109 110int 111pfctl_command_tables(int argc, char *argv[], char *tname, 112 const char *command, char *file, const char *anchor, const char *ruleset, 113 int opts) 114{ 115 if (tname == NULL || command == NULL) 116 usage(); 117 return pfctl_table(argc, argv, tname, command, file, anchor, ruleset, 118 opts); 119} 120 121int 122pfctl_table(int argc, char *argv[], char *tname, const char *command, 123 char *file, const char *anchor, const char *ruleset, int opts) 124{ 125 struct pfr_table table; 126 struct pfr_buffer b, b2; 127 struct pfr_addr *a, *a2; 128 int nadd = 0, ndel = 0, nchange = 0, nzero = 0; 129 int rv = 0, flags = 0, nmatch = 0; 130 void *p; 131 132 if (command == NULL) 133 usage(); 134 if (opts & PF_OPT_NOACTION) 135 flags |= PFR_FLAG_DUMMY; 136 137 bzero(&b, sizeof(b)); 138 bzero(&b2, sizeof(b2)); 139 bzero(&table, sizeof(table)); 140 if (tname != NULL) { 141 if (strlen(tname) >= PF_TABLE_NAME_SIZE) 142 usage(); 143 if (strlcpy(table.pfrt_name, tname, 144 sizeof(table.pfrt_name)) >= sizeof(table.pfrt_name)) 145 errx(1, "pfctl_table: strlcpy"); 146 } 147 if (strlcpy(table.pfrt_anchor, anchor, 148 sizeof(table.pfrt_anchor)) >= sizeof(table.pfrt_anchor) || 149 strlcpy(table.pfrt_ruleset, ruleset, 150 sizeof(table.pfrt_ruleset)) >= sizeof(table.pfrt_ruleset)) 151 errx(1, "pfctl_table: strlcpy"); 152 153 if (!strcmp(command, "-F")) { 154 if (argc || file != NULL) 155 usage(); 156 RVTEST(pfr_clr_tables(&table, &ndel, flags)); 157 xprintf(opts, "%d tables deleted", ndel); 158 } else if (!strcmp(command, "-s")) { 159 b.pfrb_type = (opts & PF_OPT_VERBOSE2) ? 160 PFRB_TSTATS : PFRB_TABLES; 161 if (argc || file != NULL) 162 usage(); 163 for (;;) { 164 pfr_buf_grow(&b, b.pfrb_size); 165 b.pfrb_size = b.pfrb_msize; 166 if (opts & PF_OPT_VERBOSE2) 167 RVTEST(pfr_get_tstats(&table, 168 b.pfrb_caddr, &b.pfrb_size, flags)); 169 else 170 RVTEST(pfr_get_tables(&table, 171 b.pfrb_caddr, &b.pfrb_size, flags)); 172 if (b.pfrb_size <= b.pfrb_msize) 173 break; 174 } 175 PFRB_FOREACH(p, &b) 176 if (opts & PF_OPT_VERBOSE2) 177 print_tstats(p, opts & PF_OPT_DEBUG); 178 else 179 print_table(p, opts & PF_OPT_VERBOSE, 180 opts & PF_OPT_DEBUG); 181 } else if (!strcmp(command, "kill")) { 182 if (argc || file != NULL) 183 usage(); 184 RVTEST(pfr_del_tables(&table, 1, &ndel, flags)); 185 xprintf(opts, "%d table deleted", ndel); 186 } else if (!strcmp(command, "flush")) { 187 if (argc || file != NULL) 188 usage(); 189 RVTEST(pfr_clr_addrs(&table, &ndel, flags)); 190 xprintf(opts, "%d addresses deleted", ndel); 191 } else if (!strcmp(command, "add")) { 192 b.pfrb_type = PFRB_ADDRS; 193 if (load_addr(&b, argc, argv, file, 0)) 194 goto _error; 195 CREATE_TABLE; 196 if (opts & PF_OPT_VERBOSE) 197 flags |= PFR_FLAG_FEEDBACK; 198 RVTEST(pfr_add_addrs(&table, b.pfrb_caddr, b.pfrb_size, 199 &nadd, flags)); 200 xprintf(opts, "%d/%d addresses added", nadd, b.pfrb_size); 201 if (opts & PF_OPT_VERBOSE) 202 PFRB_FOREACH(a, &b) 203 if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 204 print_addrx(a, NULL, 205 opts & PF_OPT_USEDNS); 206 } else if (!strcmp(command, "delete")) { 207 b.pfrb_type = PFRB_ADDRS; 208 if (load_addr(&b, argc, argv, file, 0)) 209 goto _error; 210 if (opts & PF_OPT_VERBOSE) 211 flags |= PFR_FLAG_FEEDBACK; 212 RVTEST(pfr_del_addrs(&table, b.pfrb_caddr, b.pfrb_size, 213 &ndel, flags)); 214 xprintf(opts, "%d/%d addresses deleted", ndel, b.pfrb_size); 215 if (opts & PF_OPT_VERBOSE) 216 PFRB_FOREACH(a, &b) 217 if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 218 print_addrx(a, NULL, 219 opts & PF_OPT_USEDNS); 220 } else if (!strcmp(command, "replace")) { 221 b.pfrb_type = PFRB_ADDRS; 222 if (load_addr(&b, argc, argv, file, 0)) 223 goto _error; 224 CREATE_TABLE; 225 if (opts & PF_OPT_VERBOSE) 226 flags |= PFR_FLAG_FEEDBACK; 227 for (;;) { 228 int sz2 = b.pfrb_msize; 229 230 RVTEST(pfr_set_addrs(&table, b.pfrb_caddr, b.pfrb_size, 231 &sz2, &nadd, &ndel, &nchange, flags)); 232 if (sz2 <= b.pfrb_msize) { 233 b.pfrb_size = sz2; 234 break; 235 } else 236 pfr_buf_grow(&b, sz2); 237 } 238 if (nadd) 239 xprintf(opts, "%d addresses added", nadd); 240 if (ndel) 241 xprintf(opts, "%d addresses deleted", ndel); 242 if (nchange) 243 xprintf(opts, "%d addresses changed", nchange); 244 if (!nadd && !ndel && !nchange) 245 xprintf(opts, "no changes"); 246 if (opts & PF_OPT_VERBOSE) 247 PFRB_FOREACH(a, &b) 248 if ((opts & PF_OPT_VERBOSE2) || a->pfra_fback) 249 print_addrx(a, NULL, 250 opts & PF_OPT_USEDNS); 251 } else if (!strcmp(command, "show")) { 252 b.pfrb_type = (opts & PF_OPT_VERBOSE) ? 253 PFRB_ASTATS : PFRB_ADDRS; 254 if (argc || file != NULL) 255 usage(); 256 for (;;) { 257 pfr_buf_grow(&b, b.pfrb_size); 258 b.pfrb_size = b.pfrb_msize; 259 if (opts & PF_OPT_VERBOSE) 260 RVTEST(pfr_get_astats(&table, b.pfrb_caddr, 261 &b.pfrb_size, flags)); 262 else 263 RVTEST(pfr_get_addrs(&table, b.pfrb_caddr, 264 &b.pfrb_size, flags)); 265 if (b.pfrb_size <= b.pfrb_msize) 266 break; 267 } 268 PFRB_FOREACH(p, &b) 269 if (opts & PF_OPT_VERBOSE) 270 print_astats(p, opts & PF_OPT_USEDNS); 271 else 272 print_addrx(p, NULL, opts & PF_OPT_USEDNS); 273 } else if (!strcmp(command, "test")) { 274 b.pfrb_type = PFRB_ADDRS; 275 b2.pfrb_type = PFRB_ADDRS; 276 277 if (load_addr(&b, argc, argv, file, 1)) 278 goto _error; 279 if (opts & PF_OPT_VERBOSE2) { 280 flags |= PFR_FLAG_REPLACE; 281 PFRB_FOREACH(a, &b) 282 if (pfr_buf_add(&b2, a)) 283 err(1, "duplicate buffer"); 284 } 285 RVTEST(pfr_tst_addrs(&table, b.pfrb_caddr, b.pfrb_size, 286 &nmatch, flags)); 287 xprintf(opts, "%d/%d addresses match", nmatch, b.pfrb_size); 288 if (opts & PF_OPT_VERBOSE && !(opts & PF_OPT_VERBOSE2)) 289 PFRB_FOREACH(a, &b) 290 if (a->pfra_fback == PFR_FB_MATCH) 291 print_addrx(a, NULL, 292 opts & PF_OPT_USEDNS); 293 if (opts & PF_OPT_VERBOSE2) { 294 a2 = NULL; 295 PFRB_FOREACH(a, &b) { 296 a2 = pfr_buf_next(&b2, a2); 297 print_addrx(a2, a, opts & PF_OPT_USEDNS); 298 } 299 } 300 if (nmatch < b.pfrb_size) 301 rv = 2; 302 } else if (!strcmp(command, "zero")) { 303 if (argc || file != NULL) 304 usage(); 305 flags |= PFR_FLAG_ADDRSTOO; 306 RVTEST(pfr_clr_tstats(&table, 1, &nzero, flags)); 307 xprintf(opts, "%d table/stats cleared", nzero); 308 } else 309 warnx("pfctl_table: unknown command '%s'", command); 310 goto _cleanup; 311 312_error: 313 rv = -1; 314_cleanup: 315 pfr_buf_clear(&b); 316 pfr_buf_clear(&b2); 317 return (rv); 318} 319 320void 321print_table(struct pfr_table *ta, int verbose, int debug) 322{ 323 if (!debug && !(ta->pfrt_flags & PFR_TFLAG_ACTIVE)) 324 return; 325 if (verbose) { 326 printf("%c%c%c%c%c%c\t%s", 327 (ta->pfrt_flags & PFR_TFLAG_CONST) ? 'c' : '-', 328 (ta->pfrt_flags & PFR_TFLAG_PERSIST) ? 'p' : '-', 329 (ta->pfrt_flags & PFR_TFLAG_ACTIVE) ? 'a' : '-', 330 (ta->pfrt_flags & PFR_TFLAG_INACTIVE) ? 'i' : '-', 331 (ta->pfrt_flags & PFR_TFLAG_REFERENCED) ? 'r' : '-', 332 (ta->pfrt_flags & PFR_TFLAG_REFDANCHOR) ? 'h' : '-', 333 ta->pfrt_name); 334 if (ta->pfrt_anchor[0]) 335 printf("\t%s", ta->pfrt_anchor); 336 if (ta->pfrt_ruleset[0]) 337 printf(":%s", ta->pfrt_ruleset); 338 puts(""); 339 } else 340 puts(ta->pfrt_name); 341} 342 343void 344print_tstats(struct pfr_tstats *ts, int debug) 345{ 346 time_t time = ts->pfrts_tzero; 347 int dir, op; 348 349 if (!debug && !(ts->pfrts_flags & PFR_TFLAG_ACTIVE)) 350 return; 351 print_table(&ts->pfrts_t, 1, debug); 352 printf("\tAddresses: %d\n", ts->pfrts_cnt); 353 printf("\tCleared: %s", ctime(&time)); 354 printf("\tReferences: [ Anchors: %-18d Rules: %-18d ]\n", 355 ts->pfrts_refcnt[PFR_REFCNT_ANCHOR], 356 ts->pfrts_refcnt[PFR_REFCNT_RULE]);
|
355 stats_text[dir][op], 356 ts->pfrts_packets[dir][op], 357 ts->pfrts_bytes[dir][op]); 358} 359 360int 361load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, 362 int nonetwork) 363{ 364 while (argc--) 365 if (append_addr(b, *argv++, nonetwork)) { 366 if (errno) 367 warn("cannot decode %s", argv[-1]); 368 return (-1); 369 } 370 if (pfr_buf_load(b, file, nonetwork, append_addr)) { 371 warn("cannot load %s", file); 372 return (-1); 373 } 374 return (0); 375} 376 377void 378print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) 379{ 380 char ch, buf[256] = "{error}"; 381 char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' }; 382 unsigned int fback, hostnet; 383 384 fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback; 385 ch = (fback < sizeof(fb)/sizeof(*fb)) ? fb[fback] : '?'; 386 hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32; 387 inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf)); 388 printf("%c %c%s", ch, (ad->pfra_not?'!':' '), buf); 389 if (ad->pfra_net < hostnet) 390 printf("/%d", ad->pfra_net); 391 if (rad != NULL && fback != PFR_FB_NONE) { 392 if (strlcpy(buf, "{error}", sizeof(buf)) >= sizeof(buf)) 393 errx(1, "print_addrx: strlcpy"); 394 inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf)); 395 printf("\t%c%s", (rad->pfra_not?'!':' '), buf); 396 if (rad->pfra_net < hostnet) 397 printf("/%d", rad->pfra_net); 398 } 399 if (rad != NULL && fback == PFR_FB_NONE) 400 printf("\t nomatch"); 401 if (dns && ad->pfra_net == hostnet) { 402 char host[NI_MAXHOST]; 403 union sockaddr_union sa; 404 405 strlcpy(host, "?", sizeof(host)); 406 bzero(&sa, sizeof(sa)); 407 sa.sa.sa_family = ad->pfra_af; 408 if (sa.sa.sa_family == AF_INET) { 409 sa.sa.sa_len = sizeof(sa.sin); 410 sa.sin.sin_addr = ad->pfra_ip4addr; 411 } else { 412 sa.sa.sa_len = sizeof(sa.sin6); 413 sa.sin6.sin6_addr = ad->pfra_ip6addr; 414 } 415 if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host), 416 NULL, 0, NI_NAMEREQD) == 0) 417 printf("\t(%s)", host); 418 } 419 printf("\n"); 420} 421 422void 423print_astats(struct pfr_astats *as, int dns) 424{ 425 time_t time = as->pfras_tzero; 426 int dir, op; 427 428 print_addrx(&as->pfras_a, NULL, dns); 429 printf("\tCleared: %s", ctime(&time)); 430 for (dir = 0; dir < PFR_DIR_MAX; dir++) 431 for (op = 0; op < PFR_OP_ADDR_MAX; op++)
| 362 stats_text[dir][op], 363 ts->pfrts_packets[dir][op], 364 ts->pfrts_bytes[dir][op]); 365} 366 367int 368load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, 369 int nonetwork) 370{ 371 while (argc--) 372 if (append_addr(b, *argv++, nonetwork)) { 373 if (errno) 374 warn("cannot decode %s", argv[-1]); 375 return (-1); 376 } 377 if (pfr_buf_load(b, file, nonetwork, append_addr)) { 378 warn("cannot load %s", file); 379 return (-1); 380 } 381 return (0); 382} 383 384void 385print_addrx(struct pfr_addr *ad, struct pfr_addr *rad, int dns) 386{ 387 char ch, buf[256] = "{error}"; 388 char fb[] = { ' ', 'M', 'A', 'D', 'C', 'Z', 'X', ' ', 'Y' }; 389 unsigned int fback, hostnet; 390 391 fback = (rad != NULL) ? rad->pfra_fback : ad->pfra_fback; 392 ch = (fback < sizeof(fb)/sizeof(*fb)) ? fb[fback] : '?'; 393 hostnet = (ad->pfra_af == AF_INET6) ? 128 : 32; 394 inet_ntop(ad->pfra_af, &ad->pfra_u, buf, sizeof(buf)); 395 printf("%c %c%s", ch, (ad->pfra_not?'!':' '), buf); 396 if (ad->pfra_net < hostnet) 397 printf("/%d", ad->pfra_net); 398 if (rad != NULL && fback != PFR_FB_NONE) { 399 if (strlcpy(buf, "{error}", sizeof(buf)) >= sizeof(buf)) 400 errx(1, "print_addrx: strlcpy"); 401 inet_ntop(rad->pfra_af, &rad->pfra_u, buf, sizeof(buf)); 402 printf("\t%c%s", (rad->pfra_not?'!':' '), buf); 403 if (rad->pfra_net < hostnet) 404 printf("/%d", rad->pfra_net); 405 } 406 if (rad != NULL && fback == PFR_FB_NONE) 407 printf("\t nomatch"); 408 if (dns && ad->pfra_net == hostnet) { 409 char host[NI_MAXHOST]; 410 union sockaddr_union sa; 411 412 strlcpy(host, "?", sizeof(host)); 413 bzero(&sa, sizeof(sa)); 414 sa.sa.sa_family = ad->pfra_af; 415 if (sa.sa.sa_family == AF_INET) { 416 sa.sa.sa_len = sizeof(sa.sin); 417 sa.sin.sin_addr = ad->pfra_ip4addr; 418 } else { 419 sa.sa.sa_len = sizeof(sa.sin6); 420 sa.sin6.sin6_addr = ad->pfra_ip6addr; 421 } 422 if (getnameinfo(&sa.sa, sa.sa.sa_len, host, sizeof(host), 423 NULL, 0, NI_NAMEREQD) == 0) 424 printf("\t(%s)", host); 425 } 426 printf("\n"); 427} 428 429void 430print_astats(struct pfr_astats *as, int dns) 431{ 432 time_t time = as->pfras_tzero; 433 int dir, op; 434 435 print_addrx(&as->pfras_a, NULL, dns); 436 printf("\tCleared: %s", ctime(&time)); 437 for (dir = 0; dir < PFR_DIR_MAX; dir++) 438 for (op = 0; op < PFR_OP_ADDR_MAX; op++)
|
433 stats_text[dir][op], 434 as->pfras_packets[dir][op], 435 as->pfras_bytes[dir][op]); 436} 437 438void 439radix_perror(void) 440{ 441 extern char *__progname; 442 fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno)); 443} 444 445int 446pfctl_define_table(char *name, int flags, int addrs, const char *anchor, 447 const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) 448{ 449 struct pfr_table tbl; 450 451 bzero(&tbl, sizeof(tbl)); 452 if (strlcpy(tbl.pfrt_name, name, 453 sizeof(tbl.pfrt_name)) >= sizeof(tbl.pfrt_name) || 454 strlcpy(tbl.pfrt_anchor, anchor, 455 sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) || 456 strlcpy(tbl.pfrt_ruleset, ruleset, 457 sizeof(tbl.pfrt_ruleset)) >= sizeof(tbl.pfrt_ruleset)) 458 errx(1, "pfctl_define_table: strlcpy"); 459 tbl.pfrt_flags = flags; 460 461 return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, 462 NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0); 463} 464 465void 466warn_namespace_collision(const char *filter) 467{ 468 struct pfr_buffer b; 469 struct pfr_table *t; 470 const char *name = NULL, *lastcoll; 471 int coll = 0; 472 473 bzero(&b, sizeof(b)); 474 b.pfrb_type = PFRB_TABLES; 475 for (;;) { 476 pfr_buf_grow(&b, b.pfrb_size); 477 b.pfrb_size = b.pfrb_msize; 478 if (pfr_get_tables(NULL, b.pfrb_caddr, 479 &b.pfrb_size, PFR_FLAG_ALLRSETS)) 480 err(1, "pfr_get_tables"); 481 if (b.pfrb_size <= b.pfrb_msize) 482 break; 483 } 484 PFRB_FOREACH(t, &b) { 485 if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE)) 486 continue; 487 if (filter != NULL && strcmp(filter, t->pfrt_name)) 488 continue; 489 if (!t->pfrt_anchor[0]) 490 name = t->pfrt_name; 491 else if (name != NULL && !strcmp(name, t->pfrt_name)) { 492 coll++; 493 lastcoll = name; 494 name = NULL; 495 } 496 } 497 if (coll == 1) 498 warnx("warning: namespace collision with <%s> global table.", 499 lastcoll); 500 else if (coll > 1) 501 warnx("warning: namespace collisions with %d global tables.", 502 coll); 503 pfr_buf_clear(&b); 504} 505 506void 507xprintf(int opts, const char *fmt, ...) 508{ 509 va_list args; 510 511 if (opts & PF_OPT_QUIET) 512 return; 513 514 va_start(args, fmt); 515 vfprintf(stderr, fmt, args); 516 va_end(args); 517 518 if (opts & PF_OPT_DUMMYACTION) 519 fprintf(stderr, " (dummy).\n"); 520 else if (opts & PF_OPT_NOACTION) 521 fprintf(stderr, " (syntax only).\n"); 522 else 523 fprintf(stderr, ".\n"); 524}
| 440 stats_text[dir][op], 441 as->pfras_packets[dir][op], 442 as->pfras_bytes[dir][op]); 443} 444 445void 446radix_perror(void) 447{ 448 extern char *__progname; 449 fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno)); 450} 451 452int 453pfctl_define_table(char *name, int flags, int addrs, const char *anchor, 454 const char *ruleset, struct pfr_buffer *ab, u_int32_t ticket) 455{ 456 struct pfr_table tbl; 457 458 bzero(&tbl, sizeof(tbl)); 459 if (strlcpy(tbl.pfrt_name, name, 460 sizeof(tbl.pfrt_name)) >= sizeof(tbl.pfrt_name) || 461 strlcpy(tbl.pfrt_anchor, anchor, 462 sizeof(tbl.pfrt_anchor)) >= sizeof(tbl.pfrt_anchor) || 463 strlcpy(tbl.pfrt_ruleset, ruleset, 464 sizeof(tbl.pfrt_ruleset)) >= sizeof(tbl.pfrt_ruleset)) 465 errx(1, "pfctl_define_table: strlcpy"); 466 tbl.pfrt_flags = flags; 467 468 return pfr_ina_define(&tbl, ab->pfrb_caddr, ab->pfrb_size, NULL, 469 NULL, ticket, addrs ? PFR_FLAG_ADDRSTOO : 0); 470} 471 472void 473warn_namespace_collision(const char *filter) 474{ 475 struct pfr_buffer b; 476 struct pfr_table *t; 477 const char *name = NULL, *lastcoll; 478 int coll = 0; 479 480 bzero(&b, sizeof(b)); 481 b.pfrb_type = PFRB_TABLES; 482 for (;;) { 483 pfr_buf_grow(&b, b.pfrb_size); 484 b.pfrb_size = b.pfrb_msize; 485 if (pfr_get_tables(NULL, b.pfrb_caddr, 486 &b.pfrb_size, PFR_FLAG_ALLRSETS)) 487 err(1, "pfr_get_tables"); 488 if (b.pfrb_size <= b.pfrb_msize) 489 break; 490 } 491 PFRB_FOREACH(t, &b) { 492 if (!(t->pfrt_flags & PFR_TFLAG_ACTIVE)) 493 continue; 494 if (filter != NULL && strcmp(filter, t->pfrt_name)) 495 continue; 496 if (!t->pfrt_anchor[0]) 497 name = t->pfrt_name; 498 else if (name != NULL && !strcmp(name, t->pfrt_name)) { 499 coll++; 500 lastcoll = name; 501 name = NULL; 502 } 503 } 504 if (coll == 1) 505 warnx("warning: namespace collision with <%s> global table.", 506 lastcoll); 507 else if (coll > 1) 508 warnx("warning: namespace collisions with %d global tables.", 509 coll); 510 pfr_buf_clear(&b); 511} 512 513void 514xprintf(int opts, const char *fmt, ...) 515{ 516 va_list args; 517 518 if (opts & PF_OPT_QUIET) 519 return; 520 521 va_start(args, fmt); 522 vfprintf(stderr, fmt, args); 523 va_end(args); 524 525 if (opts & PF_OPT_DUMMYACTION) 526 fprintf(stderr, " (dummy).\n"); 527 else if (opts & PF_OPT_NOACTION) 528 fprintf(stderr, " (syntax only).\n"); 529 else 530 fprintf(stderr, ".\n"); 531}
|