1 1.19 thorpej /* $NetBSD: pf_table.c,v 1.19 2020/12/04 00:41:10 thorpej Exp $ */ 2 1.14 yamt /* $OpenBSD: pf_table.c,v 1.70 2007/05/23 11:53:45 markus 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.13 lukem #include <sys/cdefs.h> 35 1.19 thorpej __KERNEL_RCSID(0, "$NetBSD: pf_table.c,v 1.19 2020/12/04 00:41:10 thorpej Exp $"); 36 1.13 lukem 37 1.2 itojun #ifdef _KERNEL_OPT 38 1.2 itojun #include "opt_inet.h" 39 1.2 itojun #endif 40 1.2 itojun 41 1.1 itojun #include <sys/param.h> 42 1.1 itojun #include <sys/systm.h> 43 1.1 itojun #include <sys/socket.h> 44 1.1 itojun #include <sys/mbuf.h> 45 1.1 itojun #include <sys/kernel.h> 46 1.1 itojun 47 1.1 itojun #include <net/if.h> 48 1.1 itojun #include <net/route.h> 49 1.1 itojun #include <netinet/in.h> 50 1.14 yamt #ifndef __NetBSD__ 51 1.1 itojun #include <netinet/ip_ipsp.h> 52 1.14 yamt #endif /* !__NetBSD__ */ 53 1.1 itojun #include <net/pfvar.h> 54 1.1 itojun 55 1.14 yamt #define ACCEPT_FLAGS(flags, oklist) \ 56 1.1 itojun do { \ 57 1.1 itojun if ((flags & ~(oklist)) & \ 58 1.1 itojun PFR_FLAG_ALLMASK) \ 59 1.1 itojun return (EINVAL); \ 60 1.1 itojun } while (0) 61 1.1 itojun 62 1.14 yamt #define COPYIN(from, to, size, flags) \ 63 1.1 itojun ((flags & PFR_FLAG_USERIOCTL) ? \ 64 1.1 itojun copyin((from), (to), (size)) : \ 65 1.1 itojun (bcopy((from), (to), (size)), 0)) 66 1.1 itojun 67 1.14 yamt #define COPYOUT(from, to, size, flags) \ 68 1.1 itojun ((flags & PFR_FLAG_USERIOCTL) ? \ 69 1.1 itojun copyout((from), (to), (size)) : \ 70 1.1 itojun (bcopy((from), (to), (size)), 0)) 71 1.1 itojun 72 1.1 itojun #define FILLIN_SIN(sin, addr) \ 73 1.1 itojun do { \ 74 1.1 itojun (sin).sin_len = sizeof(sin); \ 75 1.1 itojun (sin).sin_family = AF_INET; \ 76 1.1 itojun (sin).sin_addr = (addr); \ 77 1.1 itojun } while (0) 78 1.1 itojun 79 1.1 itojun #define FILLIN_SIN6(sin6, addr) \ 80 1.1 itojun do { \ 81 1.1 itojun (sin6).sin6_len = sizeof(sin6); \ 82 1.1 itojun (sin6).sin6_family = AF_INET6; \ 83 1.1 itojun (sin6).sin6_addr = (addr); \ 84 1.1 itojun } while (0) 85 1.1 itojun 86 1.1 itojun #define SWAP(type, a1, a2) \ 87 1.1 itojun do { \ 88 1.1 itojun type tmp = a1; \ 89 1.1 itojun a1 = a2; \ 90 1.1 itojun a2 = tmp; \ 91 1.1 itojun } while (0) 92 1.1 itojun 93 1.1 itojun #define SUNION2PF(su, af) (((af)==AF_INET) ? \ 94 1.1 itojun (struct pf_addr *)&(su)->sin.sin_addr : \ 95 1.1 itojun (struct pf_addr *)&(su)->sin6.sin6_addr) 96 1.1 itojun 97 1.1 itojun #define AF_BITS(af) (((af)==AF_INET)?32:128) 98 1.1 itojun #define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af)) 99 1.1 itojun #define KENTRY_NETWORK(ke) ((ke)->pfrke_net < AF_BITS((ke)->pfrke_af)) 100 1.1 itojun #define KENTRY_RNF_ROOT(ke) \ 101 1.1 itojun ((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0) 102 1.1 itojun 103 1.1 itojun #define NO_ADDRESSES (-1) 104 1.1 itojun #define ENQUEUE_UNMARKED_ONLY (1) 105 1.1 itojun #define INVERT_NEG_FLAG (1) 106 1.1 itojun 107 1.1 itojun struct pfr_walktree { 108 1.1 itojun enum pfrw_op { 109 1.1 itojun PFRW_MARK, 110 1.1 itojun PFRW_SWEEP, 111 1.1 itojun PFRW_ENQUEUE, 112 1.1 itojun PFRW_GET_ADDRS, 113 1.1 itojun PFRW_GET_ASTATS, 114 1.1 itojun PFRW_POOL_GET, 115 1.1 itojun PFRW_DYNADDR_UPDATE 116 1.1 itojun } pfrw_op; 117 1.1 itojun union { 118 1.1 itojun struct pfr_addr *pfrw1_addr; 119 1.1 itojun struct pfr_astats *pfrw1_astats; 120 1.1 itojun struct pfr_kentryworkq *pfrw1_workq; 121 1.1 itojun struct pfr_kentry *pfrw1_kentry; 122 1.1 itojun struct pfi_dynaddr *pfrw1_dyn; 123 1.1 itojun } pfrw_1; 124 1.1 itojun int pfrw_free; 125 1.1 itojun int pfrw_flags; 126 1.1 itojun }; 127 1.1 itojun #define pfrw_addr pfrw_1.pfrw1_addr 128 1.1 itojun #define pfrw_astats pfrw_1.pfrw1_astats 129 1.1 itojun #define pfrw_workq pfrw_1.pfrw1_workq 130 1.1 itojun #define pfrw_kentry pfrw_1.pfrw1_kentry 131 1.1 itojun #define pfrw_dyn pfrw_1.pfrw1_dyn 132 1.1 itojun #define pfrw_cnt pfrw_free 133 1.1 itojun 134 1.1 itojun #define senderr(e) do { rv = (e); goto _bad; } while (0) 135 1.1 itojun 136 1.1 itojun struct pool pfr_ktable_pl; 137 1.1 itojun struct pool pfr_kentry_pl; 138 1.6 peter struct pool pfr_kentry_pl2; 139 1.1 itojun struct sockaddr_in pfr_sin; 140 1.1 itojun struct sockaddr_in6 pfr_sin6; 141 1.1 itojun union sockaddr_union pfr_mask; 142 1.1 itojun struct pf_addr pfr_ffaddr; 143 1.1 itojun 144 1.1 itojun void pfr_copyout_addr(struct pfr_addr *, 145 1.1 itojun struct pfr_kentry *ke); 146 1.1 itojun int pfr_validate_addr(struct pfr_addr *); 147 1.1 itojun void pfr_enqueue_addrs(struct pfr_ktable *, 148 1.1 itojun struct pfr_kentryworkq *, int *, int); 149 1.1 itojun void pfr_mark_addrs(struct pfr_ktable *); 150 1.1 itojun struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *, 151 1.1 itojun struct pfr_addr *, int); 152 1.6 peter struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int); 153 1.1 itojun void pfr_destroy_kentries(struct pfr_kentryworkq *); 154 1.1 itojun void pfr_destroy_kentry(struct pfr_kentry *); 155 1.1 itojun void pfr_insert_kentries(struct pfr_ktable *, 156 1.1 itojun struct pfr_kentryworkq *, long); 157 1.1 itojun void pfr_remove_kentries(struct pfr_ktable *, 158 1.1 itojun struct pfr_kentryworkq *); 159 1.1 itojun void pfr_clstats_kentries(struct pfr_kentryworkq *, long, 160 1.1 itojun int); 161 1.1 itojun void pfr_reset_feedback(struct pfr_addr *, int, int); 162 1.1 itojun void pfr_prepare_network(union sockaddr_union *, int, int); 163 1.1 itojun int pfr_route_kentry(struct pfr_ktable *, 164 1.1 itojun struct pfr_kentry *); 165 1.1 itojun int pfr_unroute_kentry(struct pfr_ktable *, 166 1.1 itojun struct pfr_kentry *); 167 1.1 itojun int pfr_walktree(struct radix_node *, void *); 168 1.1 itojun int pfr_validate_table(struct pfr_table *, int, int); 169 1.6 peter int pfr_fix_anchor(char *); 170 1.1 itojun void pfr_commit_ktable(struct pfr_ktable *, long); 171 1.1 itojun void pfr_insert_ktables(struct pfr_ktableworkq *); 172 1.1 itojun void pfr_insert_ktable(struct pfr_ktable *); 173 1.1 itojun void pfr_setflags_ktables(struct pfr_ktableworkq *); 174 1.1 itojun void pfr_setflags_ktable(struct pfr_ktable *, int); 175 1.1 itojun void pfr_clstats_ktables(struct pfr_ktableworkq *, long, 176 1.1 itojun int); 177 1.1 itojun void pfr_clstats_ktable(struct pfr_ktable *, long, int); 178 1.1 itojun struct pfr_ktable *pfr_create_ktable(struct pfr_table *, long, int); 179 1.1 itojun void pfr_destroy_ktables(struct pfr_ktableworkq *, int); 180 1.1 itojun void pfr_destroy_ktable(struct pfr_ktable *, int); 181 1.1 itojun int pfr_ktable_compare(struct pfr_ktable *, 182 1.1 itojun struct pfr_ktable *); 183 1.1 itojun struct pfr_ktable *pfr_lookup_table(struct pfr_table *); 184 1.1 itojun void pfr_clean_node_mask(struct pfr_ktable *, 185 1.1 itojun struct pfr_kentryworkq *); 186 1.1 itojun int pfr_table_count(struct pfr_table *, int); 187 1.1 itojun int pfr_skip_table(struct pfr_table *, 188 1.1 itojun struct pfr_ktable *, int); 189 1.1 itojun struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int); 190 1.1 itojun 191 1.1 itojun RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare); 192 1.1 itojun RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare); 193 1.1 itojun 194 1.1 itojun struct pfr_ktablehead pfr_ktables; 195 1.1 itojun struct pfr_table pfr_nulltable; 196 1.1 itojun int pfr_ktable_cnt; 197 1.1 itojun 198 1.1 itojun void 199 1.1 itojun pfr_initialize(void) 200 1.1 itojun { 201 1.12 ad #ifdef __NetBSD__ 202 1.12 ad pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0, 203 1.17 hauke "pfrktable", &pool_allocator_nointr, IPL_NET); 204 1.12 ad pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0, 205 1.17 hauke "pfrkentry", &pool_allocator_nointr, IPL_NET); 206 1.12 ad pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0, 207 1.12 ad "pfrkentry2", NULL, IPL_SOFTNET); 208 1.12 ad #else 209 1.1 itojun pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0, 210 1.5 yamt "pfrktable", &pool_allocator_oldnointr); 211 1.1 itojun pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0, 212 1.5 yamt "pfrkentry", &pool_allocator_oldnointr); 213 1.6 peter pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0, 214 1.6 peter "pfrkentry2", NULL); 215 1.14 yamt #endif /* !__NetBSD__ */ 216 1.1 itojun 217 1.1 itojun pfr_sin.sin_len = sizeof(pfr_sin); 218 1.1 itojun pfr_sin.sin_family = AF_INET; 219 1.1 itojun pfr_sin6.sin6_len = sizeof(pfr_sin6); 220 1.1 itojun pfr_sin6.sin6_family = AF_INET6; 221 1.1 itojun 222 1.1 itojun memset(&pfr_ffaddr, 0xff, sizeof(pfr_ffaddr)); 223 1.1 itojun } 224 1.1 itojun 225 1.16 ahoka #ifdef _MODULE 226 1.16 ahoka void 227 1.16 ahoka pfr_destroy(void) 228 1.16 ahoka { 229 1.16 ahoka pool_destroy(&pfr_ktable_pl); 230 1.16 ahoka pool_destroy(&pfr_kentry_pl); 231 1.16 ahoka pool_destroy(&pfr_kentry_pl2); 232 1.16 ahoka } 233 1.16 ahoka #endif /* _MODULE */ 234 1.16 ahoka 235 1.1 itojun int 236 1.1 itojun pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags) 237 1.1 itojun { 238 1.1 itojun struct pfr_ktable *kt; 239 1.1 itojun struct pfr_kentryworkq workq; 240 1.2 itojun int s = 0; 241 1.1 itojun 242 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY); 243 1.1 itojun if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) 244 1.1 itojun return (EINVAL); 245 1.1 itojun kt = pfr_lookup_table(tbl); 246 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 247 1.1 itojun return (ESRCH); 248 1.1 itojun if (kt->pfrkt_flags & PFR_TFLAG_CONST) 249 1.1 itojun return (EPERM); 250 1.1 itojun pfr_enqueue_addrs(kt, &workq, ndel, 0); 251 1.1 itojun 252 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 253 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 254 1.1 itojun s = splsoftnet(); 255 1.1 itojun pfr_remove_kentries(kt, &workq); 256 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 257 1.1 itojun splx(s); 258 1.1 itojun if (kt->pfrkt_cnt) { 259 1.1 itojun printf("pfr_clr_addrs: corruption detected (%d).\n", 260 1.1 itojun kt->pfrkt_cnt); 261 1.1 itojun kt->pfrkt_cnt = 0; 262 1.1 itojun } 263 1.1 itojun } 264 1.1 itojun return (0); 265 1.1 itojun } 266 1.1 itojun 267 1.1 itojun int 268 1.1 itojun pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 269 1.1 itojun int *nadd, int flags) 270 1.1 itojun { 271 1.1 itojun struct pfr_ktable *kt, *tmpkt; 272 1.1 itojun struct pfr_kentryworkq workq; 273 1.1 itojun struct pfr_kentry *p, *q; 274 1.1 itojun struct pfr_addr ad; 275 1.5 yamt int i, rv, s = 0 /* XXX gcc */, xadd = 0; 276 1.5 yamt long tzero = time_second; 277 1.1 itojun 278 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | 279 1.14 yamt PFR_FLAG_FEEDBACK); 280 1.1 itojun if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) 281 1.1 itojun return (EINVAL); 282 1.1 itojun kt = pfr_lookup_table(tbl); 283 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 284 1.1 itojun return (ESRCH); 285 1.1 itojun if (kt->pfrkt_flags & PFR_TFLAG_CONST) 286 1.1 itojun return (EPERM); 287 1.1 itojun tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0); 288 1.1 itojun if (tmpkt == NULL) 289 1.1 itojun return (ENOMEM); 290 1.1 itojun SLIST_INIT(&workq); 291 1.1 itojun for (i = 0; i < size; i++) { 292 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 293 1.1 itojun senderr(EFAULT); 294 1.1 itojun if (pfr_validate_addr(&ad)) 295 1.1 itojun senderr(EINVAL); 296 1.1 itojun p = pfr_lookup_addr(kt, &ad, 1); 297 1.1 itojun q = pfr_lookup_addr(tmpkt, &ad, 1); 298 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) { 299 1.1 itojun if (q != NULL) 300 1.1 itojun ad.pfra_fback = PFR_FB_DUPLICATE; 301 1.1 itojun else if (p == NULL) 302 1.1 itojun ad.pfra_fback = PFR_FB_ADDED; 303 1.1 itojun else if (p->pfrke_not != ad.pfra_not) 304 1.1 itojun ad.pfra_fback = PFR_FB_CONFLICT; 305 1.1 itojun else 306 1.1 itojun ad.pfra_fback = PFR_FB_NONE; 307 1.1 itojun } 308 1.1 itojun if (p == NULL && q == NULL) { 309 1.14 yamt p = pfr_create_kentry(&ad, 310 1.14 yamt !(flags & PFR_FLAG_USERIOCTL)); 311 1.1 itojun if (p == NULL) 312 1.1 itojun senderr(ENOMEM); 313 1.1 itojun if (pfr_route_kentry(tmpkt, p)) { 314 1.1 itojun pfr_destroy_kentry(p); 315 1.1 itojun ad.pfra_fback = PFR_FB_NONE; 316 1.1 itojun } else { 317 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrke_workq); 318 1.1 itojun xadd++; 319 1.1 itojun } 320 1.1 itojun } 321 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 322 1.14 yamt if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) 323 1.1 itojun senderr(EFAULT); 324 1.1 itojun } 325 1.1 itojun pfr_clean_node_mask(tmpkt, &workq); 326 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 327 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 328 1.1 itojun s = splsoftnet(); 329 1.1 itojun pfr_insert_kentries(kt, &workq, tzero); 330 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 331 1.1 itojun splx(s); 332 1.1 itojun } else 333 1.1 itojun pfr_destroy_kentries(&workq); 334 1.1 itojun if (nadd != NULL) 335 1.1 itojun *nadd = xadd; 336 1.1 itojun pfr_destroy_ktable(tmpkt, 0); 337 1.1 itojun return (0); 338 1.1 itojun _bad: 339 1.1 itojun pfr_clean_node_mask(tmpkt, &workq); 340 1.1 itojun pfr_destroy_kentries(&workq); 341 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 342 1.1 itojun pfr_reset_feedback(addr, size, flags); 343 1.1 itojun pfr_destroy_ktable(tmpkt, 0); 344 1.1 itojun return (rv); 345 1.1 itojun } 346 1.1 itojun 347 1.1 itojun int 348 1.1 itojun pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 349 1.1 itojun int *ndel, int flags) 350 1.1 itojun { 351 1.1 itojun struct pfr_ktable *kt; 352 1.1 itojun struct pfr_kentryworkq workq; 353 1.1 itojun struct pfr_kentry *p; 354 1.1 itojun struct pfr_addr ad; 355 1.5 yamt int i, rv, s = 0 /* XXX gcc */, xdel = 0, log = 1; 356 1.1 itojun 357 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | 358 1.14 yamt PFR_FLAG_FEEDBACK); 359 1.1 itojun if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) 360 1.1 itojun return (EINVAL); 361 1.1 itojun kt = pfr_lookup_table(tbl); 362 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 363 1.1 itojun return (ESRCH); 364 1.1 itojun if (kt->pfrkt_flags & PFR_TFLAG_CONST) 365 1.1 itojun return (EPERM); 366 1.5 yamt /* 367 1.5 yamt * there are two algorithms to choose from here. 368 1.5 yamt * with: 369 1.5 yamt * n: number of addresses to delete 370 1.5 yamt * N: number of addresses in the table 371 1.5 yamt * 372 1.5 yamt * one is O(N) and is better for large 'n' 373 1.5 yamt * one is O(n*LOG(N)) and is better for small 'n' 374 1.5 yamt * 375 1.5 yamt * following code try to decide which one is best. 376 1.5 yamt */ 377 1.5 yamt for (i = kt->pfrkt_cnt; i > 0; i >>= 1) 378 1.5 yamt log++; 379 1.5 yamt if (size > kt->pfrkt_cnt/log) { 380 1.5 yamt /* full table scan */ 381 1.5 yamt pfr_mark_addrs(kt); 382 1.5 yamt } else { 383 1.5 yamt /* iterate over addresses to delete */ 384 1.5 yamt for (i = 0; i < size; i++) { 385 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 386 1.5 yamt return (EFAULT); 387 1.5 yamt if (pfr_validate_addr(&ad)) 388 1.5 yamt return (EINVAL); 389 1.5 yamt p = pfr_lookup_addr(kt, &ad, 1); 390 1.5 yamt if (p != NULL) 391 1.5 yamt p->pfrke_mark = 0; 392 1.5 yamt } 393 1.5 yamt } 394 1.1 itojun SLIST_INIT(&workq); 395 1.1 itojun for (i = 0; i < size; i++) { 396 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 397 1.1 itojun senderr(EFAULT); 398 1.1 itojun if (pfr_validate_addr(&ad)) 399 1.1 itojun senderr(EINVAL); 400 1.1 itojun p = pfr_lookup_addr(kt, &ad, 1); 401 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) { 402 1.1 itojun if (p == NULL) 403 1.1 itojun ad.pfra_fback = PFR_FB_NONE; 404 1.1 itojun else if (p->pfrke_not != ad.pfra_not) 405 1.1 itojun ad.pfra_fback = PFR_FB_CONFLICT; 406 1.1 itojun else if (p->pfrke_mark) 407 1.1 itojun ad.pfra_fback = PFR_FB_DUPLICATE; 408 1.1 itojun else 409 1.1 itojun ad.pfra_fback = PFR_FB_DELETED; 410 1.1 itojun } 411 1.1 itojun if (p != NULL && p->pfrke_not == ad.pfra_not && 412 1.1 itojun !p->pfrke_mark) { 413 1.1 itojun p->pfrke_mark = 1; 414 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrke_workq); 415 1.1 itojun xdel++; 416 1.1 itojun } 417 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 418 1.14 yamt if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) 419 1.1 itojun senderr(EFAULT); 420 1.1 itojun } 421 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 422 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 423 1.1 itojun s = splsoftnet(); 424 1.1 itojun pfr_remove_kentries(kt, &workq); 425 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 426 1.1 itojun splx(s); 427 1.1 itojun } 428 1.1 itojun if (ndel != NULL) 429 1.1 itojun *ndel = xdel; 430 1.1 itojun return (0); 431 1.1 itojun _bad: 432 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 433 1.1 itojun pfr_reset_feedback(addr, size, flags); 434 1.1 itojun return (rv); 435 1.1 itojun } 436 1.1 itojun 437 1.1 itojun int 438 1.1 itojun pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 439 1.14 yamt int *size2, int *nadd, int *ndel, int *nchange, int flags, 440 1.14 yamt u_int32_t ignore_pfrt_flags) 441 1.1 itojun { 442 1.1 itojun struct pfr_ktable *kt, *tmpkt; 443 1.1 itojun struct pfr_kentryworkq addq, delq, changeq; 444 1.1 itojun struct pfr_kentry *p, *q; 445 1.1 itojun struct pfr_addr ad; 446 1.5 yamt int i, rv, s = 0 /* XXX gcc */, xadd = 0, xdel = 0, 447 1.5 yamt xchange = 0; 448 1.5 yamt long tzero = time_second; 449 1.1 itojun 450 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | 451 1.14 yamt PFR_FLAG_FEEDBACK); 452 1.14 yamt if (pfr_validate_table(tbl, ignore_pfrt_flags, flags & 453 1.14 yamt PFR_FLAG_USERIOCTL)) 454 1.1 itojun return (EINVAL); 455 1.1 itojun kt = pfr_lookup_table(tbl); 456 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 457 1.1 itojun return (ESRCH); 458 1.1 itojun if (kt->pfrkt_flags & PFR_TFLAG_CONST) 459 1.1 itojun return (EPERM); 460 1.1 itojun tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0); 461 1.1 itojun if (tmpkt == NULL) 462 1.1 itojun return (ENOMEM); 463 1.1 itojun pfr_mark_addrs(kt); 464 1.1 itojun SLIST_INIT(&addq); 465 1.1 itojun SLIST_INIT(&delq); 466 1.1 itojun SLIST_INIT(&changeq); 467 1.1 itojun for (i = 0; i < size; i++) { 468 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 469 1.1 itojun senderr(EFAULT); 470 1.1 itojun if (pfr_validate_addr(&ad)) 471 1.1 itojun senderr(EINVAL); 472 1.1 itojun ad.pfra_fback = PFR_FB_NONE; 473 1.1 itojun p = pfr_lookup_addr(kt, &ad, 1); 474 1.1 itojun if (p != NULL) { 475 1.1 itojun if (p->pfrke_mark) { 476 1.1 itojun ad.pfra_fback = PFR_FB_DUPLICATE; 477 1.1 itojun goto _skip; 478 1.1 itojun } 479 1.1 itojun p->pfrke_mark = 1; 480 1.1 itojun if (p->pfrke_not != ad.pfra_not) { 481 1.1 itojun SLIST_INSERT_HEAD(&changeq, p, pfrke_workq); 482 1.1 itojun ad.pfra_fback = PFR_FB_CHANGED; 483 1.1 itojun xchange++; 484 1.1 itojun } 485 1.1 itojun } else { 486 1.1 itojun q = pfr_lookup_addr(tmpkt, &ad, 1); 487 1.1 itojun if (q != NULL) { 488 1.1 itojun ad.pfra_fback = PFR_FB_DUPLICATE; 489 1.1 itojun goto _skip; 490 1.1 itojun } 491 1.14 yamt p = pfr_create_kentry(&ad, 492 1.14 yamt !(flags & PFR_FLAG_USERIOCTL)); 493 1.1 itojun if (p == NULL) 494 1.1 itojun senderr(ENOMEM); 495 1.1 itojun if (pfr_route_kentry(tmpkt, p)) { 496 1.1 itojun pfr_destroy_kentry(p); 497 1.1 itojun ad.pfra_fback = PFR_FB_NONE; 498 1.1 itojun } else { 499 1.1 itojun SLIST_INSERT_HEAD(&addq, p, pfrke_workq); 500 1.1 itojun ad.pfra_fback = PFR_FB_ADDED; 501 1.1 itojun xadd++; 502 1.1 itojun } 503 1.1 itojun } 504 1.1 itojun _skip: 505 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 506 1.14 yamt if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) 507 1.1 itojun senderr(EFAULT); 508 1.1 itojun } 509 1.1 itojun pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY); 510 1.1 itojun if ((flags & PFR_FLAG_FEEDBACK) && *size2) { 511 1.1 itojun if (*size2 < size+xdel) { 512 1.1 itojun *size2 = size+xdel; 513 1.1 itojun senderr(0); 514 1.1 itojun } 515 1.1 itojun i = 0; 516 1.1 itojun SLIST_FOREACH(p, &delq, pfrke_workq) { 517 1.1 itojun pfr_copyout_addr(&ad, p); 518 1.1 itojun ad.pfra_fback = PFR_FB_DELETED; 519 1.14 yamt if (COPYOUT(&ad, addr+size+i, sizeof(ad), flags)) 520 1.1 itojun senderr(EFAULT); 521 1.1 itojun i++; 522 1.1 itojun } 523 1.1 itojun } 524 1.1 itojun pfr_clean_node_mask(tmpkt, &addq); 525 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 526 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 527 1.1 itojun s = splsoftnet(); 528 1.1 itojun pfr_insert_kentries(kt, &addq, tzero); 529 1.1 itojun pfr_remove_kentries(kt, &delq); 530 1.1 itojun pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG); 531 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 532 1.1 itojun splx(s); 533 1.1 itojun } else 534 1.1 itojun pfr_destroy_kentries(&addq); 535 1.1 itojun if (nadd != NULL) 536 1.1 itojun *nadd = xadd; 537 1.1 itojun if (ndel != NULL) 538 1.1 itojun *ndel = xdel; 539 1.1 itojun if (nchange != NULL) 540 1.1 itojun *nchange = xchange; 541 1.1 itojun if ((flags & PFR_FLAG_FEEDBACK) && size2) 542 1.1 itojun *size2 = size+xdel; 543 1.1 itojun pfr_destroy_ktable(tmpkt, 0); 544 1.1 itojun return (0); 545 1.1 itojun _bad: 546 1.1 itojun pfr_clean_node_mask(tmpkt, &addq); 547 1.1 itojun pfr_destroy_kentries(&addq); 548 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 549 1.1 itojun pfr_reset_feedback(addr, size, flags); 550 1.1 itojun pfr_destroy_ktable(tmpkt, 0); 551 1.1 itojun return (rv); 552 1.1 itojun } 553 1.1 itojun 554 1.1 itojun int 555 1.1 itojun pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, 556 1.1 itojun int *nmatch, int flags) 557 1.1 itojun { 558 1.1 itojun struct pfr_ktable *kt; 559 1.1 itojun struct pfr_kentry *p; 560 1.1 itojun struct pfr_addr ad; 561 1.1 itojun int i, xmatch = 0; 562 1.1 itojun 563 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_REPLACE); 564 1.1 itojun if (pfr_validate_table(tbl, 0, 0)) 565 1.1 itojun return (EINVAL); 566 1.1 itojun kt = pfr_lookup_table(tbl); 567 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 568 1.1 itojun return (ESRCH); 569 1.1 itojun 570 1.1 itojun for (i = 0; i < size; i++) { 571 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 572 1.1 itojun return (EFAULT); 573 1.1 itojun if (pfr_validate_addr(&ad)) 574 1.1 itojun return (EINVAL); 575 1.1 itojun if (ADDR_NETWORK(&ad)) 576 1.1 itojun return (EINVAL); 577 1.1 itojun p = pfr_lookup_addr(kt, &ad, 0); 578 1.1 itojun if (flags & PFR_FLAG_REPLACE) 579 1.1 itojun pfr_copyout_addr(&ad, p); 580 1.1 itojun ad.pfra_fback = (p == NULL) ? PFR_FB_NONE : 581 1.1 itojun (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH); 582 1.1 itojun if (p != NULL && !p->pfrke_not) 583 1.1 itojun xmatch++; 584 1.14 yamt if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) 585 1.1 itojun return (EFAULT); 586 1.1 itojun } 587 1.1 itojun if (nmatch != NULL) 588 1.1 itojun *nmatch = xmatch; 589 1.1 itojun return (0); 590 1.1 itojun } 591 1.1 itojun 592 1.1 itojun int 593 1.1 itojun pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size, 594 1.1 itojun int flags) 595 1.1 itojun { 596 1.1 itojun struct pfr_ktable *kt; 597 1.1 itojun struct pfr_walktree w; 598 1.1 itojun int rv; 599 1.1 itojun 600 1.14 yamt ACCEPT_FLAGS(flags, 0); 601 1.1 itojun if (pfr_validate_table(tbl, 0, 0)) 602 1.1 itojun return (EINVAL); 603 1.1 itojun kt = pfr_lookup_table(tbl); 604 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 605 1.1 itojun return (ESRCH); 606 1.1 itojun if (kt->pfrkt_cnt > *size) { 607 1.1 itojun *size = kt->pfrkt_cnt; 608 1.1 itojun return (0); 609 1.1 itojun } 610 1.1 itojun 611 1.1 itojun bzero(&w, sizeof(w)); 612 1.1 itojun w.pfrw_op = PFRW_GET_ADDRS; 613 1.1 itojun w.pfrw_addr = addr; 614 1.1 itojun w.pfrw_free = kt->pfrkt_cnt; 615 1.1 itojun w.pfrw_flags = flags; 616 1.1 itojun rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 617 1.1 itojun if (!rv) 618 1.1 itojun rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 619 1.1 itojun if (rv) 620 1.1 itojun return (rv); 621 1.1 itojun 622 1.1 itojun if (w.pfrw_free) { 623 1.1 itojun printf("pfr_get_addrs: corruption detected (%d).\n", 624 1.1 itojun w.pfrw_free); 625 1.1 itojun return (ENOTTY); 626 1.1 itojun } 627 1.1 itojun *size = kt->pfrkt_cnt; 628 1.1 itojun return (0); 629 1.1 itojun } 630 1.1 itojun 631 1.1 itojun int 632 1.1 itojun pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size, 633 1.1 itojun int flags) 634 1.1 itojun { 635 1.1 itojun struct pfr_ktable *kt; 636 1.1 itojun struct pfr_walktree w; 637 1.1 itojun struct pfr_kentryworkq workq; 638 1.5 yamt int rv, s = 0 /* XXX gcc */; 639 1.5 yamt long tzero = time_second; 640 1.1 itojun 641 1.14 yamt /* XXX PFR_FLAG_CLSTATS disabled */ 642 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC); 643 1.1 itojun if (pfr_validate_table(tbl, 0, 0)) 644 1.1 itojun return (EINVAL); 645 1.1 itojun kt = pfr_lookup_table(tbl); 646 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 647 1.1 itojun return (ESRCH); 648 1.1 itojun if (kt->pfrkt_cnt > *size) { 649 1.1 itojun *size = kt->pfrkt_cnt; 650 1.1 itojun return (0); 651 1.1 itojun } 652 1.1 itojun 653 1.1 itojun bzero(&w, sizeof(w)); 654 1.1 itojun w.pfrw_op = PFRW_GET_ASTATS; 655 1.1 itojun w.pfrw_astats = addr; 656 1.1 itojun w.pfrw_free = kt->pfrkt_cnt; 657 1.1 itojun w.pfrw_flags = flags; 658 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 659 1.1 itojun s = splsoftnet(); 660 1.1 itojun rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 661 1.1 itojun if (!rv) 662 1.1 itojun rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 663 1.1 itojun if (!rv && (flags & PFR_FLAG_CLSTATS)) { 664 1.1 itojun pfr_enqueue_addrs(kt, &workq, NULL, 0); 665 1.1 itojun pfr_clstats_kentries(&workq, tzero, 0); 666 1.1 itojun } 667 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 668 1.1 itojun splx(s); 669 1.1 itojun if (rv) 670 1.1 itojun return (rv); 671 1.1 itojun 672 1.1 itojun if (w.pfrw_free) { 673 1.1 itojun printf("pfr_get_astats: corruption detected (%d).\n", 674 1.1 itojun w.pfrw_free); 675 1.1 itojun return (ENOTTY); 676 1.1 itojun } 677 1.1 itojun *size = kt->pfrkt_cnt; 678 1.1 itojun return (0); 679 1.1 itojun } 680 1.1 itojun 681 1.1 itojun int 682 1.1 itojun pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size, 683 1.1 itojun int *nzero, int flags) 684 1.1 itojun { 685 1.1 itojun struct pfr_ktable *kt; 686 1.1 itojun struct pfr_kentryworkq workq; 687 1.1 itojun struct pfr_kentry *p; 688 1.1 itojun struct pfr_addr ad; 689 1.2 itojun int i, rv, s = 0, xzero = 0; 690 1.1 itojun 691 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | 692 1.14 yamt PFR_FLAG_FEEDBACK); 693 1.1 itojun if (pfr_validate_table(tbl, 0, 0)) 694 1.1 itojun return (EINVAL); 695 1.1 itojun kt = pfr_lookup_table(tbl); 696 1.1 itojun if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 697 1.1 itojun return (ESRCH); 698 1.1 itojun SLIST_INIT(&workq); 699 1.1 itojun for (i = 0; i < size; i++) { 700 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 701 1.1 itojun senderr(EFAULT); 702 1.1 itojun if (pfr_validate_addr(&ad)) 703 1.1 itojun senderr(EINVAL); 704 1.1 itojun p = pfr_lookup_addr(kt, &ad, 1); 705 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) { 706 1.1 itojun ad.pfra_fback = (p != NULL) ? 707 1.1 itojun PFR_FB_CLEARED : PFR_FB_NONE; 708 1.14 yamt if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) 709 1.1 itojun senderr(EFAULT); 710 1.1 itojun } 711 1.1 itojun if (p != NULL) { 712 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrke_workq); 713 1.1 itojun xzero++; 714 1.1 itojun } 715 1.1 itojun } 716 1.1 itojun 717 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 718 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 719 1.1 itojun s = splsoftnet(); 720 1.1 itojun pfr_clstats_kentries(&workq, 0, 0); 721 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 722 1.1 itojun splx(s); 723 1.1 itojun } 724 1.1 itojun if (nzero != NULL) 725 1.1 itojun *nzero = xzero; 726 1.1 itojun return (0); 727 1.1 itojun _bad: 728 1.1 itojun if (flags & PFR_FLAG_FEEDBACK) 729 1.1 itojun pfr_reset_feedback(addr, size, flags); 730 1.1 itojun return (rv); 731 1.1 itojun } 732 1.1 itojun 733 1.1 itojun int 734 1.1 itojun pfr_validate_addr(struct pfr_addr *ad) 735 1.1 itojun { 736 1.1 itojun int i; 737 1.1 itojun 738 1.1 itojun switch (ad->pfra_af) { 739 1.5 yamt #ifdef INET 740 1.1 itojun case AF_INET: 741 1.1 itojun if (ad->pfra_net > 32) 742 1.1 itojun return (-1); 743 1.1 itojun break; 744 1.5 yamt #endif /* INET */ 745 1.5 yamt #ifdef INET6 746 1.1 itojun case AF_INET6: 747 1.1 itojun if (ad->pfra_net > 128) 748 1.1 itojun return (-1); 749 1.1 itojun break; 750 1.5 yamt #endif /* INET6 */ 751 1.1 itojun default: 752 1.1 itojun return (-1); 753 1.1 itojun } 754 1.1 itojun if (ad->pfra_net < 128 && 755 1.11 christos (((char *)ad)[ad->pfra_net/8] & (0xFF >> (ad->pfra_net%8)))) 756 1.1 itojun return (-1); 757 1.1 itojun for (i = (ad->pfra_net+7)/8; i < sizeof(ad->pfra_u); i++) 758 1.11 christos if (((char *)ad)[i]) 759 1.1 itojun return (-1); 760 1.1 itojun if (ad->pfra_not && ad->pfra_not != 1) 761 1.1 itojun return (-1); 762 1.1 itojun if (ad->pfra_fback) 763 1.1 itojun return (-1); 764 1.1 itojun return (0); 765 1.1 itojun } 766 1.1 itojun 767 1.1 itojun void 768 1.1 itojun pfr_enqueue_addrs(struct pfr_ktable *kt, struct pfr_kentryworkq *workq, 769 1.1 itojun int *naddr, int sweep) 770 1.1 itojun { 771 1.1 itojun struct pfr_walktree w; 772 1.1 itojun 773 1.1 itojun SLIST_INIT(workq); 774 1.1 itojun bzero(&w, sizeof(w)); 775 1.1 itojun w.pfrw_op = sweep ? PFRW_SWEEP : PFRW_ENQUEUE; 776 1.1 itojun w.pfrw_workq = workq; 777 1.1 itojun if (kt->pfrkt_ip4 != NULL) 778 1.1 itojun if (rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w)) 779 1.1 itojun printf("pfr_enqueue_addrs: IPv4 walktree failed.\n"); 780 1.1 itojun if (kt->pfrkt_ip6 != NULL) 781 1.1 itojun if (rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w)) 782 1.1 itojun printf("pfr_enqueue_addrs: IPv6 walktree failed.\n"); 783 1.1 itojun if (naddr != NULL) 784 1.1 itojun *naddr = w.pfrw_cnt; 785 1.1 itojun } 786 1.1 itojun 787 1.1 itojun void 788 1.1 itojun pfr_mark_addrs(struct pfr_ktable *kt) 789 1.1 itojun { 790 1.1 itojun struct pfr_walktree w; 791 1.1 itojun 792 1.1 itojun bzero(&w, sizeof(w)); 793 1.1 itojun w.pfrw_op = PFRW_MARK; 794 1.1 itojun if (rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w)) 795 1.1 itojun printf("pfr_mark_addrs: IPv4 walktree failed.\n"); 796 1.1 itojun if (rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w)) 797 1.1 itojun printf("pfr_mark_addrs: IPv6 walktree failed.\n"); 798 1.1 itojun } 799 1.1 itojun 800 1.1 itojun 801 1.1 itojun struct pfr_kentry * 802 1.1 itojun pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact) 803 1.1 itojun { 804 1.1 itojun union sockaddr_union sa, mask; 805 1.5 yamt struct radix_node_head *head = (void *)0xdeadb; 806 1.1 itojun struct pfr_kentry *ke; 807 1.1 itojun int s; 808 1.1 itojun 809 1.1 itojun bzero(&sa, sizeof(sa)); 810 1.1 itojun if (ad->pfra_af == AF_INET) { 811 1.1 itojun FILLIN_SIN(sa.sin, ad->pfra_ip4addr); 812 1.1 itojun head = kt->pfrkt_ip4; 813 1.5 yamt } else if ( ad->pfra_af == AF_INET6 ) { 814 1.1 itojun FILLIN_SIN6(sa.sin6, ad->pfra_ip6addr); 815 1.1 itojun head = kt->pfrkt_ip6; 816 1.1 itojun } 817 1.1 itojun if (ADDR_NETWORK(ad)) { 818 1.1 itojun pfr_prepare_network(&mask, ad->pfra_af, ad->pfra_net); 819 1.1 itojun s = splsoftnet(); /* rn_lookup makes use of globals */ 820 1.1 itojun ke = (struct pfr_kentry *)rn_lookup(&sa, &mask, head); 821 1.1 itojun splx(s); 822 1.1 itojun if (ke && KENTRY_RNF_ROOT(ke)) 823 1.1 itojun ke = NULL; 824 1.1 itojun } else { 825 1.1 itojun ke = (struct pfr_kentry *)rn_match(&sa, head); 826 1.1 itojun if (ke && KENTRY_RNF_ROOT(ke)) 827 1.1 itojun ke = NULL; 828 1.1 itojun if (exact && ke && KENTRY_NETWORK(ke)) 829 1.1 itojun ke = NULL; 830 1.1 itojun } 831 1.1 itojun return (ke); 832 1.1 itojun } 833 1.1 itojun 834 1.1 itojun struct pfr_kentry * 835 1.6 peter pfr_create_kentry(struct pfr_addr *ad, int intr) 836 1.1 itojun { 837 1.1 itojun struct pfr_kentry *ke; 838 1.1 itojun 839 1.6 peter if (intr) 840 1.6 peter ke = pool_get(&pfr_kentry_pl2, PR_NOWAIT); 841 1.6 peter else 842 1.6 peter ke = pool_get(&pfr_kentry_pl, PR_NOWAIT); 843 1.1 itojun if (ke == NULL) 844 1.1 itojun return (NULL); 845 1.1 itojun bzero(ke, sizeof(*ke)); 846 1.1 itojun 847 1.1 itojun if (ad->pfra_af == AF_INET) 848 1.1 itojun FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr); 849 1.5 yamt else if (ad->pfra_af == AF_INET6) 850 1.1 itojun FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr); 851 1.1 itojun ke->pfrke_af = ad->pfra_af; 852 1.1 itojun ke->pfrke_net = ad->pfra_net; 853 1.1 itojun ke->pfrke_not = ad->pfra_not; 854 1.6 peter ke->pfrke_intrpool = intr; 855 1.1 itojun return (ke); 856 1.1 itojun } 857 1.1 itojun 858 1.1 itojun void 859 1.1 itojun pfr_destroy_kentries(struct pfr_kentryworkq *workq) 860 1.1 itojun { 861 1.1 itojun struct pfr_kentry *p, *q; 862 1.1 itojun 863 1.1 itojun for (p = SLIST_FIRST(workq); p != NULL; p = q) { 864 1.1 itojun q = SLIST_NEXT(p, pfrke_workq); 865 1.1 itojun pfr_destroy_kentry(p); 866 1.1 itojun } 867 1.1 itojun } 868 1.1 itojun 869 1.1 itojun void 870 1.1 itojun pfr_destroy_kentry(struct pfr_kentry *ke) 871 1.1 itojun { 872 1.6 peter if (ke->pfrke_intrpool) 873 1.6 peter pool_put(&pfr_kentry_pl2, ke); 874 1.6 peter else 875 1.6 peter pool_put(&pfr_kentry_pl, ke); 876 1.1 itojun } 877 1.1 itojun 878 1.1 itojun void 879 1.1 itojun pfr_insert_kentries(struct pfr_ktable *kt, 880 1.1 itojun struct pfr_kentryworkq *workq, long tzero) 881 1.1 itojun { 882 1.1 itojun struct pfr_kentry *p; 883 1.1 itojun int rv, n = 0; 884 1.1 itojun 885 1.1 itojun SLIST_FOREACH(p, workq, pfrke_workq) { 886 1.1 itojun rv = pfr_route_kentry(kt, p); 887 1.1 itojun if (rv) { 888 1.1 itojun printf("pfr_insert_kentries: cannot route entry " 889 1.1 itojun "(code=%d).\n", rv); 890 1.1 itojun break; 891 1.1 itojun } 892 1.1 itojun p->pfrke_tzero = tzero; 893 1.1 itojun n++; 894 1.1 itojun } 895 1.1 itojun kt->pfrkt_cnt += n; 896 1.1 itojun } 897 1.1 itojun 898 1.6 peter int 899 1.6 peter pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero) 900 1.6 peter { 901 1.6 peter struct pfr_kentry *p; 902 1.6 peter int rv; 903 1.6 peter 904 1.6 peter p = pfr_lookup_addr(kt, ad, 1); 905 1.6 peter if (p != NULL) 906 1.6 peter return (0); 907 1.6 peter p = pfr_create_kentry(ad, 1); 908 1.6 peter if (p == NULL) 909 1.6 peter return (EINVAL); 910 1.6 peter 911 1.6 peter rv = pfr_route_kentry(kt, p); 912 1.6 peter if (rv) 913 1.6 peter return (rv); 914 1.6 peter 915 1.6 peter p->pfrke_tzero = tzero; 916 1.6 peter kt->pfrkt_cnt++; 917 1.6 peter 918 1.6 peter return (0); 919 1.6 peter } 920 1.6 peter 921 1.1 itojun void 922 1.1 itojun pfr_remove_kentries(struct pfr_ktable *kt, 923 1.1 itojun struct pfr_kentryworkq *workq) 924 1.1 itojun { 925 1.1 itojun struct pfr_kentry *p; 926 1.1 itojun int n = 0; 927 1.1 itojun 928 1.1 itojun SLIST_FOREACH(p, workq, pfrke_workq) { 929 1.1 itojun pfr_unroute_kentry(kt, p); 930 1.1 itojun n++; 931 1.1 itojun } 932 1.1 itojun kt->pfrkt_cnt -= n; 933 1.1 itojun pfr_destroy_kentries(workq); 934 1.1 itojun } 935 1.1 itojun 936 1.1 itojun void 937 1.1 itojun pfr_clean_node_mask(struct pfr_ktable *kt, 938 1.1 itojun struct pfr_kentryworkq *workq) 939 1.1 itojun { 940 1.1 itojun struct pfr_kentry *p; 941 1.1 itojun 942 1.1 itojun SLIST_FOREACH(p, workq, pfrke_workq) 943 1.1 itojun pfr_unroute_kentry(kt, p); 944 1.1 itojun } 945 1.1 itojun 946 1.1 itojun void 947 1.1 itojun pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange) 948 1.1 itojun { 949 1.1 itojun struct pfr_kentry *p; 950 1.1 itojun int s; 951 1.1 itojun 952 1.1 itojun SLIST_FOREACH(p, workq, pfrke_workq) { 953 1.1 itojun s = splsoftnet(); 954 1.1 itojun if (negchange) 955 1.1 itojun p->pfrke_not = !p->pfrke_not; 956 1.1 itojun bzero(p->pfrke_packets, sizeof(p->pfrke_packets)); 957 1.1 itojun bzero(p->pfrke_bytes, sizeof(p->pfrke_bytes)); 958 1.1 itojun splx(s); 959 1.1 itojun p->pfrke_tzero = tzero; 960 1.1 itojun } 961 1.1 itojun } 962 1.1 itojun 963 1.1 itojun void 964 1.1 itojun pfr_reset_feedback(struct pfr_addr *addr, int size, int flags) 965 1.1 itojun { 966 1.1 itojun struct pfr_addr ad; 967 1.1 itojun int i; 968 1.1 itojun 969 1.1 itojun for (i = 0; i < size; i++) { 970 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 971 1.1 itojun break; 972 1.1 itojun ad.pfra_fback = PFR_FB_NONE; 973 1.14 yamt if (COPYOUT(&ad, addr+i, sizeof(ad), flags)) 974 1.1 itojun break; 975 1.1 itojun } 976 1.1 itojun } 977 1.1 itojun 978 1.1 itojun void 979 1.1 itojun pfr_prepare_network(union sockaddr_union *sa, int af, int net) 980 1.1 itojun { 981 1.1 itojun int i; 982 1.1 itojun 983 1.1 itojun bzero(sa, sizeof(*sa)); 984 1.1 itojun if (af == AF_INET) { 985 1.1 itojun sa->sin.sin_len = sizeof(sa->sin); 986 1.1 itojun sa->sin.sin_family = AF_INET; 987 1.18 maya sa->sin.sin_addr.s_addr = net ? htonl(~0U << (32-net)) : 0; 988 1.5 yamt } else if (af == AF_INET6) { 989 1.1 itojun sa->sin6.sin6_len = sizeof(sa->sin6); 990 1.1 itojun sa->sin6.sin6_family = AF_INET6; 991 1.1 itojun for (i = 0; i < 4; i++) { 992 1.1 itojun if (net <= 32) { 993 1.1 itojun sa->sin6.sin6_addr.s6_addr32[i] = 994 1.18 maya net ? htonl(~0U << (32-net)) : 0; 995 1.1 itojun break; 996 1.1 itojun } 997 1.1 itojun sa->sin6.sin6_addr.s6_addr32[i] = 0xFFFFFFFF; 998 1.1 itojun net -= 32; 999 1.1 itojun } 1000 1.1 itojun } 1001 1.1 itojun } 1002 1.1 itojun 1003 1.1 itojun int 1004 1.1 itojun pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke) 1005 1.1 itojun { 1006 1.1 itojun union sockaddr_union mask; 1007 1.1 itojun struct radix_node *rn; 1008 1.5 yamt struct radix_node_head *head = (void *)0xdeadb; 1009 1.1 itojun int s; 1010 1.1 itojun 1011 1.1 itojun bzero(ke->pfrke_node, sizeof(ke->pfrke_node)); 1012 1.1 itojun if (ke->pfrke_af == AF_INET) 1013 1.1 itojun head = kt->pfrkt_ip4; 1014 1.5 yamt else if (ke->pfrke_af == AF_INET6) 1015 1.1 itojun head = kt->pfrkt_ip6; 1016 1.1 itojun 1017 1.1 itojun s = splsoftnet(); 1018 1.1 itojun if (KENTRY_NETWORK(ke)) { 1019 1.1 itojun pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net); 1020 1.1 itojun rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node); 1021 1.1 itojun } else 1022 1.1 itojun rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node); 1023 1.1 itojun splx(s); 1024 1.1 itojun 1025 1.1 itojun return (rn == NULL ? -1 : 0); 1026 1.1 itojun } 1027 1.1 itojun 1028 1.1 itojun int 1029 1.1 itojun pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke) 1030 1.1 itojun { 1031 1.1 itojun union sockaddr_union mask; 1032 1.1 itojun struct radix_node *rn; 1033 1.5 yamt struct radix_node_head *head = (void *)0xdeadb; 1034 1.1 itojun int s; 1035 1.1 itojun 1036 1.1 itojun if (ke->pfrke_af == AF_INET) 1037 1.1 itojun head = kt->pfrkt_ip4; 1038 1.5 yamt else if (ke->pfrke_af == AF_INET6) 1039 1.1 itojun head = kt->pfrkt_ip6; 1040 1.1 itojun 1041 1.1 itojun s = splsoftnet(); 1042 1.1 itojun if (KENTRY_NETWORK(ke)) { 1043 1.1 itojun pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net); 1044 1.1 itojun rn = rn_delete(&ke->pfrke_sa, &mask, head); 1045 1.1 itojun } else 1046 1.1 itojun rn = rn_delete(&ke->pfrke_sa, NULL, head); 1047 1.1 itojun splx(s); 1048 1.1 itojun 1049 1.1 itojun if (rn == NULL) { 1050 1.1 itojun printf("pfr_unroute_kentry: delete failed.\n"); 1051 1.1 itojun return (-1); 1052 1.1 itojun } 1053 1.1 itojun return (0); 1054 1.1 itojun } 1055 1.1 itojun 1056 1.1 itojun void 1057 1.1 itojun pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke) 1058 1.1 itojun { 1059 1.1 itojun bzero(ad, sizeof(*ad)); 1060 1.1 itojun if (ke == NULL) 1061 1.1 itojun return; 1062 1.1 itojun ad->pfra_af = ke->pfrke_af; 1063 1.1 itojun ad->pfra_net = ke->pfrke_net; 1064 1.1 itojun ad->pfra_not = ke->pfrke_not; 1065 1.1 itojun if (ad->pfra_af == AF_INET) 1066 1.1 itojun ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr; 1067 1.5 yamt else if (ad->pfra_af == AF_INET6) 1068 1.1 itojun ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr; 1069 1.1 itojun } 1070 1.1 itojun 1071 1.1 itojun int 1072 1.1 itojun pfr_walktree(struct radix_node *rn, void *arg) 1073 1.1 itojun { 1074 1.1 itojun struct pfr_kentry *ke = (struct pfr_kentry *)rn; 1075 1.1 itojun struct pfr_walktree *w = arg; 1076 1.1 itojun int s, flags = w->pfrw_flags; 1077 1.1 itojun 1078 1.1 itojun switch (w->pfrw_op) { 1079 1.1 itojun case PFRW_MARK: 1080 1.1 itojun ke->pfrke_mark = 0; 1081 1.1 itojun break; 1082 1.1 itojun case PFRW_SWEEP: 1083 1.1 itojun if (ke->pfrke_mark) 1084 1.1 itojun break; 1085 1.1 itojun /* FALLTHROUGH */ 1086 1.1 itojun case PFRW_ENQUEUE: 1087 1.1 itojun SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq); 1088 1.1 itojun w->pfrw_cnt++; 1089 1.1 itojun break; 1090 1.1 itojun case PFRW_GET_ADDRS: 1091 1.1 itojun if (w->pfrw_free-- > 0) { 1092 1.1 itojun struct pfr_addr ad; 1093 1.1 itojun 1094 1.1 itojun pfr_copyout_addr(&ad, ke); 1095 1.1 itojun if (copyout(&ad, w->pfrw_addr, sizeof(ad))) 1096 1.1 itojun return (EFAULT); 1097 1.1 itojun w->pfrw_addr++; 1098 1.1 itojun } 1099 1.1 itojun break; 1100 1.1 itojun case PFRW_GET_ASTATS: 1101 1.1 itojun if (w->pfrw_free-- > 0) { 1102 1.1 itojun struct pfr_astats as; 1103 1.1 itojun 1104 1.1 itojun pfr_copyout_addr(&as.pfras_a, ke); 1105 1.1 itojun 1106 1.1 itojun s = splsoftnet(); 1107 1.1 itojun bcopy(ke->pfrke_packets, as.pfras_packets, 1108 1.1 itojun sizeof(as.pfras_packets)); 1109 1.1 itojun bcopy(ke->pfrke_bytes, as.pfras_bytes, 1110 1.1 itojun sizeof(as.pfras_bytes)); 1111 1.1 itojun splx(s); 1112 1.1 itojun as.pfras_tzero = ke->pfrke_tzero; 1113 1.1 itojun 1114 1.14 yamt if (COPYOUT(&as, w->pfrw_astats, sizeof(as), flags)) 1115 1.1 itojun return (EFAULT); 1116 1.1 itojun w->pfrw_astats++; 1117 1.1 itojun } 1118 1.1 itojun break; 1119 1.1 itojun case PFRW_POOL_GET: 1120 1.1 itojun if (ke->pfrke_not) 1121 1.1 itojun break; /* negative entries are ignored */ 1122 1.1 itojun if (!w->pfrw_cnt--) { 1123 1.1 itojun w->pfrw_kentry = ke; 1124 1.1 itojun return (1); /* finish search */ 1125 1.1 itojun } 1126 1.1 itojun break; 1127 1.1 itojun case PFRW_DYNADDR_UPDATE: 1128 1.1 itojun if (ke->pfrke_af == AF_INET) { 1129 1.1 itojun if (w->pfrw_dyn->pfid_acnt4++ > 0) 1130 1.1 itojun break; 1131 1.1 itojun pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net); 1132 1.1 itojun w->pfrw_dyn->pfid_addr4 = *SUNION2PF( 1133 1.1 itojun &ke->pfrke_sa, AF_INET); 1134 1.1 itojun w->pfrw_dyn->pfid_mask4 = *SUNION2PF( 1135 1.1 itojun &pfr_mask, AF_INET); 1136 1.5 yamt } else if (ke->pfrke_af == AF_INET6){ 1137 1.1 itojun if (w->pfrw_dyn->pfid_acnt6++ > 0) 1138 1.1 itojun break; 1139 1.1 itojun pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net); 1140 1.1 itojun w->pfrw_dyn->pfid_addr6 = *SUNION2PF( 1141 1.1 itojun &ke->pfrke_sa, AF_INET6); 1142 1.1 itojun w->pfrw_dyn->pfid_mask6 = *SUNION2PF( 1143 1.1 itojun &pfr_mask, AF_INET6); 1144 1.1 itojun } 1145 1.1 itojun break; 1146 1.1 itojun } 1147 1.1 itojun return (0); 1148 1.1 itojun } 1149 1.1 itojun 1150 1.1 itojun int 1151 1.1 itojun pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags) 1152 1.1 itojun { 1153 1.1 itojun struct pfr_ktableworkq workq; 1154 1.1 itojun struct pfr_ktable *p; 1155 1.2 itojun int s = 0, xdel = 0; 1156 1.1 itojun 1157 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | 1158 1.14 yamt PFR_FLAG_ALLRSETS); 1159 1.6 peter if (pfr_fix_anchor(filter->pfrt_anchor)) 1160 1.6 peter return (EINVAL); 1161 1.1 itojun if (pfr_table_count(filter, flags) < 0) 1162 1.1 itojun return (ENOENT); 1163 1.1 itojun 1164 1.1 itojun SLIST_INIT(&workq); 1165 1.1 itojun RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1166 1.1 itojun if (pfr_skip_table(filter, p, flags)) 1167 1.1 itojun continue; 1168 1.1 itojun if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR)) 1169 1.1 itojun continue; 1170 1.1 itojun if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) 1171 1.1 itojun continue; 1172 1.1 itojun p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE; 1173 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1174 1.1 itojun xdel++; 1175 1.1 itojun } 1176 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1177 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1178 1.1 itojun s = splsoftnet(); 1179 1.1 itojun pfr_setflags_ktables(&workq); 1180 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1181 1.1 itojun splx(s); 1182 1.1 itojun } 1183 1.1 itojun if (ndel != NULL) 1184 1.1 itojun *ndel = xdel; 1185 1.1 itojun return (0); 1186 1.1 itojun } 1187 1.1 itojun 1188 1.1 itojun int 1189 1.1 itojun pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags) 1190 1.1 itojun { 1191 1.1 itojun struct pfr_ktableworkq addq, changeq; 1192 1.1 itojun struct pfr_ktable *p, *q, *r, key; 1193 1.5 yamt int i, rv, s = 0 /* XXX gcc */, xadd = 0; 1194 1.5 yamt long tzero = time_second; 1195 1.1 itojun 1196 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY); 1197 1.1 itojun SLIST_INIT(&addq); 1198 1.1 itojun SLIST_INIT(&changeq); 1199 1.1 itojun for (i = 0; i < size; i++) { 1200 1.14 yamt if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1201 1.1 itojun senderr(EFAULT); 1202 1.1 itojun if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK, 1203 1.1 itojun flags & PFR_FLAG_USERIOCTL)) 1204 1.1 itojun senderr(EINVAL); 1205 1.1 itojun key.pfrkt_flags |= PFR_TFLAG_ACTIVE; 1206 1.1 itojun p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1207 1.1 itojun if (p == NULL) { 1208 1.1 itojun p = pfr_create_ktable(&key.pfrkt_t, tzero, 1); 1209 1.1 itojun if (p == NULL) 1210 1.1 itojun senderr(ENOMEM); 1211 1.1 itojun SLIST_FOREACH(q, &addq, pfrkt_workq) { 1212 1.1 itojun if (!pfr_ktable_compare(p, q)) 1213 1.1 itojun goto _skip; 1214 1.1 itojun } 1215 1.1 itojun SLIST_INSERT_HEAD(&addq, p, pfrkt_workq); 1216 1.1 itojun xadd++; 1217 1.1 itojun if (!key.pfrkt_anchor[0]) 1218 1.1 itojun goto _skip; 1219 1.1 itojun 1220 1.1 itojun /* find or create root table */ 1221 1.1 itojun bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor)); 1222 1.1 itojun r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1223 1.1 itojun if (r != NULL) { 1224 1.1 itojun p->pfrkt_root = r; 1225 1.1 itojun goto _skip; 1226 1.1 itojun } 1227 1.1 itojun SLIST_FOREACH(q, &addq, pfrkt_workq) { 1228 1.1 itojun if (!pfr_ktable_compare(&key, q)) { 1229 1.1 itojun p->pfrkt_root = q; 1230 1.1 itojun goto _skip; 1231 1.1 itojun } 1232 1.1 itojun } 1233 1.1 itojun key.pfrkt_flags = 0; 1234 1.1 itojun r = pfr_create_ktable(&key.pfrkt_t, 0, 1); 1235 1.1 itojun if (r == NULL) 1236 1.1 itojun senderr(ENOMEM); 1237 1.1 itojun SLIST_INSERT_HEAD(&addq, r, pfrkt_workq); 1238 1.1 itojun p->pfrkt_root = r; 1239 1.1 itojun } else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1240 1.1 itojun SLIST_FOREACH(q, &changeq, pfrkt_workq) 1241 1.1 itojun if (!pfr_ktable_compare(&key, q)) 1242 1.1 itojun goto _skip; 1243 1.1 itojun p->pfrkt_nflags = (p->pfrkt_flags & 1244 1.1 itojun ~PFR_TFLAG_USRMASK) | key.pfrkt_flags; 1245 1.1 itojun SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq); 1246 1.1 itojun xadd++; 1247 1.1 itojun } 1248 1.1 itojun _skip: 1249 1.1 itojun ; 1250 1.1 itojun } 1251 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1252 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1253 1.1 itojun s = splsoftnet(); 1254 1.1 itojun pfr_insert_ktables(&addq); 1255 1.1 itojun pfr_setflags_ktables(&changeq); 1256 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1257 1.1 itojun splx(s); 1258 1.1 itojun } else 1259 1.1 itojun pfr_destroy_ktables(&addq, 0); 1260 1.1 itojun if (nadd != NULL) 1261 1.1 itojun *nadd = xadd; 1262 1.1 itojun return (0); 1263 1.1 itojun _bad: 1264 1.1 itojun pfr_destroy_ktables(&addq, 0); 1265 1.1 itojun return (rv); 1266 1.1 itojun } 1267 1.1 itojun 1268 1.1 itojun int 1269 1.1 itojun pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags) 1270 1.1 itojun { 1271 1.1 itojun struct pfr_ktableworkq workq; 1272 1.1 itojun struct pfr_ktable *p, *q, key; 1273 1.2 itojun int i, s = 0, xdel = 0; 1274 1.1 itojun 1275 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY); 1276 1.1 itojun SLIST_INIT(&workq); 1277 1.1 itojun for (i = 0; i < size; i++) { 1278 1.14 yamt if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1279 1.1 itojun return (EFAULT); 1280 1.1 itojun if (pfr_validate_table(&key.pfrkt_t, 0, 1281 1.1 itojun flags & PFR_FLAG_USERIOCTL)) 1282 1.1 itojun return (EINVAL); 1283 1.1 itojun p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1284 1.1 itojun if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1285 1.1 itojun SLIST_FOREACH(q, &workq, pfrkt_workq) 1286 1.1 itojun if (!pfr_ktable_compare(p, q)) 1287 1.1 itojun goto _skip; 1288 1.1 itojun p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE; 1289 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1290 1.1 itojun xdel++; 1291 1.1 itojun } 1292 1.1 itojun _skip: 1293 1.1 itojun ; 1294 1.1 itojun } 1295 1.1 itojun 1296 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1297 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1298 1.1 itojun s = splsoftnet(); 1299 1.1 itojun pfr_setflags_ktables(&workq); 1300 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1301 1.1 itojun splx(s); 1302 1.1 itojun } 1303 1.1 itojun if (ndel != NULL) 1304 1.1 itojun *ndel = xdel; 1305 1.1 itojun return (0); 1306 1.1 itojun } 1307 1.1 itojun 1308 1.1 itojun int 1309 1.1 itojun pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size, 1310 1.1 itojun int flags) 1311 1.1 itojun { 1312 1.1 itojun struct pfr_ktable *p; 1313 1.1 itojun int n, nn; 1314 1.1 itojun 1315 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ALLRSETS); 1316 1.6 peter if (pfr_fix_anchor(filter->pfrt_anchor)) 1317 1.6 peter return (EINVAL); 1318 1.1 itojun n = nn = pfr_table_count(filter, flags); 1319 1.1 itojun if (n < 0) 1320 1.1 itojun return (ENOENT); 1321 1.1 itojun if (n > *size) { 1322 1.1 itojun *size = n; 1323 1.1 itojun return (0); 1324 1.1 itojun } 1325 1.1 itojun RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1326 1.1 itojun if (pfr_skip_table(filter, p, flags)) 1327 1.1 itojun continue; 1328 1.1 itojun if (n-- <= 0) 1329 1.1 itojun continue; 1330 1.14 yamt if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl), flags)) 1331 1.1 itojun return (EFAULT); 1332 1.1 itojun } 1333 1.1 itojun if (n) { 1334 1.1 itojun printf("pfr_get_tables: corruption detected (%d).\n", n); 1335 1.1 itojun return (ENOTTY); 1336 1.1 itojun } 1337 1.1 itojun *size = nn; 1338 1.1 itojun return (0); 1339 1.1 itojun } 1340 1.1 itojun 1341 1.1 itojun int 1342 1.1 itojun pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size, 1343 1.1 itojun int flags) 1344 1.1 itojun { 1345 1.1 itojun struct pfr_ktable *p; 1346 1.1 itojun struct pfr_ktableworkq workq; 1347 1.5 yamt int s = 0 /* XXX gcc */, n, nn; 1348 1.5 yamt long tzero = time_second; 1349 1.1 itojun 1350 1.14 yamt /* XXX PFR_FLAG_CLSTATS disabled */ 1351 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_ALLRSETS); 1352 1.6 peter if (pfr_fix_anchor(filter->pfrt_anchor)) 1353 1.6 peter return (EINVAL); 1354 1.1 itojun n = nn = pfr_table_count(filter, flags); 1355 1.1 itojun if (n < 0) 1356 1.1 itojun return (ENOENT); 1357 1.1 itojun if (n > *size) { 1358 1.1 itojun *size = n; 1359 1.1 itojun return (0); 1360 1.1 itojun } 1361 1.1 itojun SLIST_INIT(&workq); 1362 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1363 1.1 itojun s = splsoftnet(); 1364 1.1 itojun RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1365 1.1 itojun if (pfr_skip_table(filter, p, flags)) 1366 1.1 itojun continue; 1367 1.1 itojun if (n-- <= 0) 1368 1.1 itojun continue; 1369 1.1 itojun if (!(flags & PFR_FLAG_ATOMIC)) 1370 1.1 itojun s = splsoftnet(); 1371 1.14 yamt if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl), flags)) { 1372 1.1 itojun splx(s); 1373 1.1 itojun return (EFAULT); 1374 1.1 itojun } 1375 1.1 itojun if (!(flags & PFR_FLAG_ATOMIC)) 1376 1.1 itojun splx(s); 1377 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1378 1.1 itojun } 1379 1.1 itojun if (flags & PFR_FLAG_CLSTATS) 1380 1.1 itojun pfr_clstats_ktables(&workq, tzero, 1381 1.1 itojun flags & PFR_FLAG_ADDRSTOO); 1382 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1383 1.1 itojun splx(s); 1384 1.1 itojun if (n) { 1385 1.1 itojun printf("pfr_get_tstats: corruption detected (%d).\n", n); 1386 1.1 itojun return (ENOTTY); 1387 1.1 itojun } 1388 1.1 itojun *size = nn; 1389 1.1 itojun return (0); 1390 1.1 itojun } 1391 1.1 itojun 1392 1.1 itojun int 1393 1.1 itojun pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags) 1394 1.1 itojun { 1395 1.1 itojun struct pfr_ktableworkq workq; 1396 1.1 itojun struct pfr_ktable *p, key; 1397 1.5 yamt int i, s = 0 /* XXX gcc */, xzero = 0; 1398 1.5 yamt long tzero = time_second; 1399 1.1 itojun 1400 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY | 1401 1.14 yamt PFR_FLAG_ADDRSTOO); 1402 1.1 itojun SLIST_INIT(&workq); 1403 1.1 itojun for (i = 0; i < size; i++) { 1404 1.14 yamt if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1405 1.1 itojun return (EFAULT); 1406 1.1 itojun if (pfr_validate_table(&key.pfrkt_t, 0, 0)) 1407 1.1 itojun return (EINVAL); 1408 1.1 itojun p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1409 1.1 itojun if (p != NULL) { 1410 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1411 1.1 itojun xzero++; 1412 1.1 itojun } 1413 1.1 itojun } 1414 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1415 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1416 1.1 itojun s = splsoftnet(); 1417 1.1 itojun pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO); 1418 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1419 1.1 itojun splx(s); 1420 1.1 itojun } 1421 1.1 itojun if (nzero != NULL) 1422 1.1 itojun *nzero = xzero; 1423 1.1 itojun return (0); 1424 1.1 itojun } 1425 1.1 itojun 1426 1.1 itojun int 1427 1.1 itojun pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag, 1428 1.1 itojun int *nchange, int *ndel, int flags) 1429 1.1 itojun { 1430 1.1 itojun struct pfr_ktableworkq workq; 1431 1.1 itojun struct pfr_ktable *p, *q, key; 1432 1.2 itojun int i, s = 0, xchange = 0, xdel = 0; 1433 1.1 itojun 1434 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY); 1435 1.1 itojun if ((setflag & ~PFR_TFLAG_USRMASK) || 1436 1.1 itojun (clrflag & ~PFR_TFLAG_USRMASK) || 1437 1.1 itojun (setflag & clrflag)) 1438 1.1 itojun return (EINVAL); 1439 1.1 itojun SLIST_INIT(&workq); 1440 1.1 itojun for (i = 0; i < size; i++) { 1441 1.14 yamt if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t), flags)) 1442 1.1 itojun return (EFAULT); 1443 1.1 itojun if (pfr_validate_table(&key.pfrkt_t, 0, 1444 1.1 itojun flags & PFR_FLAG_USERIOCTL)) 1445 1.1 itojun return (EINVAL); 1446 1.1 itojun p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1447 1.1 itojun if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) { 1448 1.1 itojun p->pfrkt_nflags = (p->pfrkt_flags | setflag) & 1449 1.1 itojun ~clrflag; 1450 1.1 itojun if (p->pfrkt_nflags == p->pfrkt_flags) 1451 1.1 itojun goto _skip; 1452 1.1 itojun SLIST_FOREACH(q, &workq, pfrkt_workq) 1453 1.1 itojun if (!pfr_ktable_compare(p, q)) 1454 1.1 itojun goto _skip; 1455 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1456 1.1 itojun if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) && 1457 1.1 itojun (clrflag & PFR_TFLAG_PERSIST) && 1458 1.1 itojun !(p->pfrkt_flags & PFR_TFLAG_REFERENCED)) 1459 1.1 itojun xdel++; 1460 1.1 itojun else 1461 1.1 itojun xchange++; 1462 1.1 itojun } 1463 1.1 itojun _skip: 1464 1.1 itojun ; 1465 1.1 itojun } 1466 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1467 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1468 1.1 itojun s = splsoftnet(); 1469 1.1 itojun pfr_setflags_ktables(&workq); 1470 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1471 1.1 itojun splx(s); 1472 1.1 itojun } 1473 1.1 itojun if (nchange != NULL) 1474 1.1 itojun *nchange = xchange; 1475 1.1 itojun if (ndel != NULL) 1476 1.1 itojun *ndel = xdel; 1477 1.1 itojun return (0); 1478 1.1 itojun } 1479 1.1 itojun 1480 1.1 itojun int 1481 1.1 itojun pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags) 1482 1.1 itojun { 1483 1.1 itojun struct pfr_ktableworkq workq; 1484 1.1 itojun struct pfr_ktable *p; 1485 1.1 itojun struct pf_ruleset *rs; 1486 1.1 itojun int xdel = 0; 1487 1.1 itojun 1488 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1489 1.5 yamt rs = pf_find_or_create_ruleset(trs->pfrt_anchor); 1490 1.1 itojun if (rs == NULL) 1491 1.1 itojun return (ENOMEM); 1492 1.1 itojun SLIST_INIT(&workq); 1493 1.1 itojun RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1494 1.1 itojun if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1495 1.1 itojun pfr_skip_table(trs, p, 0)) 1496 1.1 itojun continue; 1497 1.1 itojun p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE; 1498 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1499 1.1 itojun xdel++; 1500 1.1 itojun } 1501 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1502 1.1 itojun pfr_setflags_ktables(&workq); 1503 1.1 itojun if (ticket != NULL) 1504 1.1 itojun *ticket = ++rs->tticket; 1505 1.1 itojun rs->topen = 1; 1506 1.1 itojun } else 1507 1.1 itojun pf_remove_if_empty_ruleset(rs); 1508 1.1 itojun if (ndel != NULL) 1509 1.1 itojun *ndel = xdel; 1510 1.1 itojun return (0); 1511 1.1 itojun } 1512 1.1 itojun 1513 1.1 itojun int 1514 1.1 itojun pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size, 1515 1.1 itojun int *nadd, int *naddr, u_int32_t ticket, int flags) 1516 1.1 itojun { 1517 1.1 itojun struct pfr_ktableworkq tableq; 1518 1.1 itojun struct pfr_kentryworkq addrq; 1519 1.1 itojun struct pfr_ktable *kt, *rt, *shadow, key; 1520 1.1 itojun struct pfr_kentry *p; 1521 1.1 itojun struct pfr_addr ad; 1522 1.1 itojun struct pf_ruleset *rs; 1523 1.1 itojun int i, rv, xadd = 0, xaddr = 0; 1524 1.1 itojun 1525 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_ADDRSTOO); 1526 1.1 itojun if (size && !(flags & PFR_FLAG_ADDRSTOO)) 1527 1.1 itojun return (EINVAL); 1528 1.1 itojun if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK, 1529 1.1 itojun flags & PFR_FLAG_USERIOCTL)) 1530 1.1 itojun return (EINVAL); 1531 1.5 yamt rs = pf_find_ruleset(tbl->pfrt_anchor); 1532 1.1 itojun if (rs == NULL || !rs->topen || ticket != rs->tticket) 1533 1.1 itojun return (EBUSY); 1534 1.1 itojun tbl->pfrt_flags |= PFR_TFLAG_INACTIVE; 1535 1.1 itojun SLIST_INIT(&tableq); 1536 1.1 itojun kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl); 1537 1.1 itojun if (kt == NULL) { 1538 1.1 itojun kt = pfr_create_ktable(tbl, 0, 1); 1539 1.1 itojun if (kt == NULL) 1540 1.1 itojun return (ENOMEM); 1541 1.1 itojun SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq); 1542 1.1 itojun xadd++; 1543 1.1 itojun if (!tbl->pfrt_anchor[0]) 1544 1.1 itojun goto _skip; 1545 1.1 itojun 1546 1.1 itojun /* find or create root table */ 1547 1.1 itojun bzero(&key, sizeof(key)); 1548 1.1 itojun strlcpy(key.pfrkt_name, tbl->pfrt_name, sizeof(key.pfrkt_name)); 1549 1.1 itojun rt = RB_FIND(pfr_ktablehead, &pfr_ktables, &key); 1550 1.1 itojun if (rt != NULL) { 1551 1.1 itojun kt->pfrkt_root = rt; 1552 1.1 itojun goto _skip; 1553 1.1 itojun } 1554 1.1 itojun rt = pfr_create_ktable(&key.pfrkt_t, 0, 1); 1555 1.1 itojun if (rt == NULL) { 1556 1.1 itojun pfr_destroy_ktables(&tableq, 0); 1557 1.1 itojun return (ENOMEM); 1558 1.1 itojun } 1559 1.1 itojun SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq); 1560 1.1 itojun kt->pfrkt_root = rt; 1561 1.1 itojun } else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE)) 1562 1.1 itojun xadd++; 1563 1.1 itojun _skip: 1564 1.1 itojun shadow = pfr_create_ktable(tbl, 0, 0); 1565 1.1 itojun if (shadow == NULL) { 1566 1.1 itojun pfr_destroy_ktables(&tableq, 0); 1567 1.1 itojun return (ENOMEM); 1568 1.1 itojun } 1569 1.1 itojun SLIST_INIT(&addrq); 1570 1.1 itojun for (i = 0; i < size; i++) { 1571 1.14 yamt if (COPYIN(addr+i, &ad, sizeof(ad), flags)) 1572 1.1 itojun senderr(EFAULT); 1573 1.1 itojun if (pfr_validate_addr(&ad)) 1574 1.1 itojun senderr(EINVAL); 1575 1.1 itojun if (pfr_lookup_addr(shadow, &ad, 1) != NULL) 1576 1.1 itojun continue; 1577 1.6 peter p = pfr_create_kentry(&ad, 0); 1578 1.1 itojun if (p == NULL) 1579 1.1 itojun senderr(ENOMEM); 1580 1.1 itojun if (pfr_route_kentry(shadow, p)) { 1581 1.1 itojun pfr_destroy_kentry(p); 1582 1.1 itojun continue; 1583 1.1 itojun } 1584 1.1 itojun SLIST_INSERT_HEAD(&addrq, p, pfrke_workq); 1585 1.1 itojun xaddr++; 1586 1.1 itojun } 1587 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1588 1.1 itojun if (kt->pfrkt_shadow != NULL) 1589 1.1 itojun pfr_destroy_ktable(kt->pfrkt_shadow, 1); 1590 1.1 itojun kt->pfrkt_flags |= PFR_TFLAG_INACTIVE; 1591 1.1 itojun pfr_insert_ktables(&tableq); 1592 1.1 itojun shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ? 1593 1.1 itojun xaddr : NO_ADDRESSES; 1594 1.1 itojun kt->pfrkt_shadow = shadow; 1595 1.1 itojun } else { 1596 1.1 itojun pfr_clean_node_mask(shadow, &addrq); 1597 1.1 itojun pfr_destroy_ktable(shadow, 0); 1598 1.1 itojun pfr_destroy_ktables(&tableq, 0); 1599 1.1 itojun pfr_destroy_kentries(&addrq); 1600 1.1 itojun } 1601 1.1 itojun if (nadd != NULL) 1602 1.1 itojun *nadd = xadd; 1603 1.1 itojun if (naddr != NULL) 1604 1.1 itojun *naddr = xaddr; 1605 1.1 itojun return (0); 1606 1.1 itojun _bad: 1607 1.1 itojun pfr_destroy_ktable(shadow, 0); 1608 1.1 itojun pfr_destroy_ktables(&tableq, 0); 1609 1.1 itojun pfr_destroy_kentries(&addrq); 1610 1.1 itojun return (rv); 1611 1.1 itojun } 1612 1.1 itojun 1613 1.1 itojun int 1614 1.1 itojun pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags) 1615 1.1 itojun { 1616 1.1 itojun struct pfr_ktableworkq workq; 1617 1.1 itojun struct pfr_ktable *p; 1618 1.1 itojun struct pf_ruleset *rs; 1619 1.1 itojun int xdel = 0; 1620 1.1 itojun 1621 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY); 1622 1.5 yamt rs = pf_find_ruleset(trs->pfrt_anchor); 1623 1.1 itojun if (rs == NULL || !rs->topen || ticket != rs->tticket) 1624 1.1 itojun return (0); 1625 1.1 itojun SLIST_INIT(&workq); 1626 1.1 itojun RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1627 1.1 itojun if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1628 1.1 itojun pfr_skip_table(trs, p, 0)) 1629 1.1 itojun continue; 1630 1.1 itojun p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE; 1631 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1632 1.1 itojun xdel++; 1633 1.1 itojun } 1634 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1635 1.1 itojun pfr_setflags_ktables(&workq); 1636 1.1 itojun rs->topen = 0; 1637 1.1 itojun pf_remove_if_empty_ruleset(rs); 1638 1.1 itojun } 1639 1.1 itojun if (ndel != NULL) 1640 1.1 itojun *ndel = xdel; 1641 1.1 itojun return (0); 1642 1.1 itojun } 1643 1.1 itojun 1644 1.1 itojun int 1645 1.1 itojun pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd, 1646 1.1 itojun int *nchange, int flags) 1647 1.1 itojun { 1648 1.4 yamt struct pfr_ktable *p, *q; 1649 1.1 itojun struct pfr_ktableworkq workq; 1650 1.1 itojun struct pf_ruleset *rs; 1651 1.5 yamt int s = 0 /* XXX gcc */, xadd = 0, xchange = 0; 1652 1.5 yamt long tzero = time_second; 1653 1.1 itojun 1654 1.14 yamt ACCEPT_FLAGS(flags, PFR_FLAG_ATOMIC | PFR_FLAG_DUMMY); 1655 1.5 yamt rs = pf_find_ruleset(trs->pfrt_anchor); 1656 1.1 itojun if (rs == NULL || !rs->topen || ticket != rs->tticket) 1657 1.1 itojun return (EBUSY); 1658 1.1 itojun 1659 1.1 itojun SLIST_INIT(&workq); 1660 1.1 itojun RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) { 1661 1.1 itojun if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) || 1662 1.1 itojun pfr_skip_table(trs, p, 0)) 1663 1.1 itojun continue; 1664 1.1 itojun SLIST_INSERT_HEAD(&workq, p, pfrkt_workq); 1665 1.1 itojun if (p->pfrkt_flags & PFR_TFLAG_ACTIVE) 1666 1.1 itojun xchange++; 1667 1.1 itojun else 1668 1.1 itojun xadd++; 1669 1.1 itojun } 1670 1.1 itojun 1671 1.1 itojun if (!(flags & PFR_FLAG_DUMMY)) { 1672 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1673 1.1 itojun s = splsoftnet(); 1674 1.4 yamt for (p = SLIST_FIRST(&workq); p != NULL; p = q) { 1675 1.4 yamt q = SLIST_NEXT(p, pfrkt_workq); 1676 1.1 itojun pfr_commit_ktable(p, tzero); 1677 1.4 yamt } 1678 1.1 itojun if (flags & PFR_FLAG_ATOMIC) 1679 1.1 itojun splx(s); 1680 1.1 itojun rs->topen = 0; 1681 1.1 itojun pf_remove_if_empty_ruleset(rs); 1682 1.1 itojun } 1683 1.1 itojun if (nadd != NULL) 1684 1.1 itojun *nadd = xadd; 1685 1.1 itojun if (nchange != NULL) 1686 1.1 itojun *nchange = xchange; 1687 1.1 itojun 1688 1.1 itojun return (0); 1689 1.1 itojun } 1690 1.1 itojun 1691 1.1 itojun void 1692 1.1 itojun pfr_commit_ktable(struct pfr_ktable *kt, long tzero) 1693 1.1 itojun { 1694 1.1 itojun struct pfr_ktable *shadow = kt->pfrkt_shadow; 1695 1.1 itojun int nflags; 1696 1.1 itojun 1697 1.1 itojun if (shadow->pfrkt_cnt == NO_ADDRESSES) { 1698 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 1699 1.1 itojun pfr_clstats_ktable(kt, tzero, 1); 1700 1.1 itojun } else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) { 1701 1.1 itojun /* kt might contain addresses */ 1702 1.1 itojun struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq; 1703 1.1 itojun struct pfr_kentry *p, *q, *next; 1704 1.1 itojun struct pfr_addr ad; 1705 1.1 itojun 1706 1.1 itojun pfr_enqueue_addrs(shadow, &addrq, NULL, 0); 1707 1.1 itojun pfr_mark_addrs(kt); 1708 1.1 itojun SLIST_INIT(&addq); 1709 1.1 itojun SLIST_INIT(&changeq); 1710 1.1 itojun SLIST_INIT(&delq); 1711 1.1 itojun SLIST_INIT(&garbageq); 1712 1.1 itojun pfr_clean_node_mask(shadow, &addrq); 1713 1.1 itojun for (p = SLIST_FIRST(&addrq); p != NULL; p = next) { 1714 1.1 itojun next = SLIST_NEXT(p, pfrke_workq); /* XXX */ 1715 1.1 itojun pfr_copyout_addr(&ad, p); 1716 1.1 itojun q = pfr_lookup_addr(kt, &ad, 1); 1717 1.1 itojun if (q != NULL) { 1718 1.1 itojun if (q->pfrke_not != p->pfrke_not) 1719 1.1 itojun SLIST_INSERT_HEAD(&changeq, q, 1720 1.1 itojun pfrke_workq); 1721 1.1 itojun q->pfrke_mark = 1; 1722 1.1 itojun SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq); 1723 1.1 itojun } else { 1724 1.1 itojun p->pfrke_tzero = tzero; 1725 1.1 itojun SLIST_INSERT_HEAD(&addq, p, pfrke_workq); 1726 1.1 itojun } 1727 1.1 itojun } 1728 1.1 itojun pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY); 1729 1.1 itojun pfr_insert_kentries(kt, &addq, tzero); 1730 1.1 itojun pfr_remove_kentries(kt, &delq); 1731 1.1 itojun pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG); 1732 1.1 itojun pfr_destroy_kentries(&garbageq); 1733 1.1 itojun } else { 1734 1.1 itojun /* kt cannot contain addresses */ 1735 1.1 itojun SWAP(struct radix_node_head *, kt->pfrkt_ip4, 1736 1.1 itojun shadow->pfrkt_ip4); 1737 1.1 itojun SWAP(struct radix_node_head *, kt->pfrkt_ip6, 1738 1.1 itojun shadow->pfrkt_ip6); 1739 1.1 itojun SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt); 1740 1.1 itojun pfr_clstats_ktable(kt, tzero, 1); 1741 1.1 itojun } 1742 1.1 itojun nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) | 1743 1.1 itojun (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE) 1744 1.1 itojun & ~PFR_TFLAG_INACTIVE; 1745 1.1 itojun pfr_destroy_ktable(shadow, 0); 1746 1.1 itojun kt->pfrkt_shadow = NULL; 1747 1.1 itojun pfr_setflags_ktable(kt, nflags); 1748 1.1 itojun } 1749 1.1 itojun 1750 1.1 itojun int 1751 1.1 itojun pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved) 1752 1.1 itojun { 1753 1.1 itojun int i; 1754 1.1 itojun 1755 1.1 itojun if (!tbl->pfrt_name[0]) 1756 1.1 itojun return (-1); 1757 1.1 itojun if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR)) 1758 1.1 itojun return (-1); 1759 1.1 itojun if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1]) 1760 1.1 itojun return (-1); 1761 1.1 itojun for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++) 1762 1.1 itojun if (tbl->pfrt_name[i]) 1763 1.1 itojun return (-1); 1764 1.6 peter if (pfr_fix_anchor(tbl->pfrt_anchor)) 1765 1.6 peter return (-1); 1766 1.1 itojun if (tbl->pfrt_flags & ~allowedflags) 1767 1.1 itojun return (-1); 1768 1.1 itojun return (0); 1769 1.1 itojun } 1770 1.1 itojun 1771 1.6 peter /* 1772 1.6 peter * Rewrite anchors referenced by tables to remove slashes 1773 1.6 peter * and check for validity. 1774 1.6 peter */ 1775 1.6 peter int 1776 1.6 peter pfr_fix_anchor(char *anchor) 1777 1.6 peter { 1778 1.6 peter size_t siz = MAXPATHLEN; 1779 1.6 peter int i; 1780 1.6 peter 1781 1.6 peter if (anchor[0] == '/') { 1782 1.6 peter char *path; 1783 1.6 peter int off; 1784 1.6 peter 1785 1.6 peter path = anchor; 1786 1.6 peter off = 1; 1787 1.6 peter while (*++path == '/') 1788 1.6 peter off++; 1789 1.19 thorpej memmove(anchor, path, siz - off); 1790 1.6 peter memset(anchor + siz - off, 0, off); 1791 1.6 peter } 1792 1.6 peter if (anchor[siz - 1]) 1793 1.6 peter return (-1); 1794 1.6 peter for (i = strlen(anchor); i < siz; i++) 1795 1.6 peter if (anchor[i]) 1796 1.6 peter return (-1); 1797 1.6 peter return (0); 1798 1.6 peter } 1799 1.6 peter 1800 1.1 itojun int 1801 1.1 itojun pfr_table_count(struct pfr_table *filter, int flags) 1802 1.1 itojun { 1803 1.1 itojun struct pf_ruleset *rs; 1804 1.1 itojun 1805 1.1 itojun if (flags & PFR_FLAG_ALLRSETS) 1806 1.1 itojun return (pfr_ktable_cnt); 1807 1.5 yamt if (filter->pfrt_anchor[0]) { 1808 1.5 yamt rs = pf_find_ruleset(filter->pfrt_anchor); 1809 1.1 itojun return ((rs != NULL) ? rs->tables : -1); 1810 1.1 itojun } 1811 1.1 itojun return (pf_main_ruleset.tables); 1812 1.1 itojun } 1813 1.1 itojun 1814 1.1 itojun int 1815 1.1 itojun pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags) 1816 1.1 itojun { 1817 1.1 itojun if (flags & PFR_FLAG_ALLRSETS) 1818 1.1 itojun return (0); 1819 1.5 yamt if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor)) 1820 1.1 itojun return (1); 1821 1.1 itojun return (0); 1822 1.1 itojun } 1823 1.1 itojun 1824 1.1 itojun void 1825 1.1 itojun pfr_insert_ktables(struct pfr_ktableworkq *workq) 1826 1.1 itojun { 1827 1.1 itojun struct pfr_ktable *p; 1828 1.1 itojun 1829 1.1 itojun SLIST_FOREACH(p, workq, pfrkt_workq) 1830 1.1 itojun pfr_insert_ktable(p); 1831 1.1 itojun } 1832 1.1 itojun 1833 1.1 itojun void 1834 1.1 itojun pfr_insert_ktable(struct pfr_ktable *kt) 1835 1.1 itojun { 1836 1.1 itojun RB_INSERT(pfr_ktablehead, &pfr_ktables, kt); 1837 1.1 itojun pfr_ktable_cnt++; 1838 1.1 itojun if (kt->pfrkt_root != NULL) 1839 1.1 itojun if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++) 1840 1.1 itojun pfr_setflags_ktable(kt->pfrkt_root, 1841 1.1 itojun kt->pfrkt_root->pfrkt_flags|PFR_TFLAG_REFDANCHOR); 1842 1.1 itojun } 1843 1.1 itojun 1844 1.1 itojun void 1845 1.1 itojun pfr_setflags_ktables(struct pfr_ktableworkq *workq) 1846 1.1 itojun { 1847 1.4 yamt struct pfr_ktable *p, *q; 1848 1.1 itojun 1849 1.4 yamt for (p = SLIST_FIRST(workq); p; p = q) { 1850 1.4 yamt q = SLIST_NEXT(p, pfrkt_workq); 1851 1.1 itojun pfr_setflags_ktable(p, p->pfrkt_nflags); 1852 1.4 yamt } 1853 1.1 itojun } 1854 1.1 itojun 1855 1.1 itojun void 1856 1.1 itojun pfr_setflags_ktable(struct pfr_ktable *kt, int newf) 1857 1.1 itojun { 1858 1.1 itojun struct pfr_kentryworkq addrq; 1859 1.1 itojun 1860 1.1 itojun if (!(newf & PFR_TFLAG_REFERENCED) && 1861 1.1 itojun !(newf & PFR_TFLAG_PERSIST)) 1862 1.1 itojun newf &= ~PFR_TFLAG_ACTIVE; 1863 1.1 itojun if (!(newf & PFR_TFLAG_ACTIVE)) 1864 1.1 itojun newf &= ~PFR_TFLAG_USRMASK; 1865 1.1 itojun if (!(newf & PFR_TFLAG_SETMASK)) { 1866 1.1 itojun RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt); 1867 1.1 itojun if (kt->pfrkt_root != NULL) 1868 1.1 itojun if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]) 1869 1.1 itojun pfr_setflags_ktable(kt->pfrkt_root, 1870 1.1 itojun kt->pfrkt_root->pfrkt_flags & 1871 1.1 itojun ~PFR_TFLAG_REFDANCHOR); 1872 1.1 itojun pfr_destroy_ktable(kt, 1); 1873 1.1 itojun pfr_ktable_cnt--; 1874 1.1 itojun return; 1875 1.1 itojun } 1876 1.1 itojun if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) { 1877 1.1 itojun pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1878 1.1 itojun pfr_remove_kentries(kt, &addrq); 1879 1.1 itojun } 1880 1.1 itojun if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) { 1881 1.1 itojun pfr_destroy_ktable(kt->pfrkt_shadow, 1); 1882 1.1 itojun kt->pfrkt_shadow = NULL; 1883 1.1 itojun } 1884 1.1 itojun kt->pfrkt_flags = newf; 1885 1.1 itojun } 1886 1.1 itojun 1887 1.1 itojun void 1888 1.1 itojun pfr_clstats_ktables(struct pfr_ktableworkq *workq, long tzero, int recurse) 1889 1.1 itojun { 1890 1.1 itojun struct pfr_ktable *p; 1891 1.1 itojun 1892 1.1 itojun SLIST_FOREACH(p, workq, pfrkt_workq) 1893 1.1 itojun pfr_clstats_ktable(p, tzero, recurse); 1894 1.1 itojun } 1895 1.1 itojun 1896 1.1 itojun void 1897 1.1 itojun pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse) 1898 1.1 itojun { 1899 1.1 itojun struct pfr_kentryworkq addrq; 1900 1.1 itojun int s; 1901 1.1 itojun 1902 1.1 itojun if (recurse) { 1903 1.1 itojun pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1904 1.1 itojun pfr_clstats_kentries(&addrq, tzero, 0); 1905 1.1 itojun } 1906 1.1 itojun s = splsoftnet(); 1907 1.1 itojun bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets)); 1908 1.1 itojun bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes)); 1909 1.1 itojun kt->pfrkt_match = kt->pfrkt_nomatch = 0; 1910 1.1 itojun splx(s); 1911 1.1 itojun kt->pfrkt_tzero = tzero; 1912 1.1 itojun } 1913 1.1 itojun 1914 1.1 itojun struct pfr_ktable * 1915 1.1 itojun pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset) 1916 1.1 itojun { 1917 1.1 itojun struct pfr_ktable *kt; 1918 1.1 itojun struct pf_ruleset *rs; 1919 1.9 peter void *h4 = NULL, *h6 = NULL; 1920 1.1 itojun 1921 1.1 itojun kt = pool_get(&pfr_ktable_pl, PR_NOWAIT); 1922 1.1 itojun if (kt == NULL) 1923 1.1 itojun return (NULL); 1924 1.1 itojun bzero(kt, sizeof(*kt)); 1925 1.1 itojun kt->pfrkt_t = *tbl; 1926 1.1 itojun 1927 1.1 itojun if (attachruleset) { 1928 1.5 yamt rs = pf_find_or_create_ruleset(tbl->pfrt_anchor); 1929 1.1 itojun if (!rs) { 1930 1.1 itojun pfr_destroy_ktable(kt, 0); 1931 1.1 itojun return (NULL); 1932 1.1 itojun } 1933 1.1 itojun kt->pfrkt_rs = rs; 1934 1.1 itojun rs->tables++; 1935 1.1 itojun } 1936 1.1 itojun 1937 1.8 christos if (!rn_inithead(&h4, offsetof(struct sockaddr_in, sin_addr) * 8)) 1938 1.8 christos goto out; 1939 1.8 christos 1940 1.8 christos if (!rn_inithead(&h6, offsetof(struct sockaddr_in6, sin6_addr) * 8)) { 1941 1.8 christos Free(h4); 1942 1.8 christos goto out; 1943 1.1 itojun } 1944 1.8 christos kt->pfrkt_ip4 = h4; 1945 1.8 christos kt->pfrkt_ip6 = h6; 1946 1.1 itojun kt->pfrkt_tzero = tzero; 1947 1.1 itojun 1948 1.1 itojun return (kt); 1949 1.8 christos out: 1950 1.8 christos pfr_destroy_ktable(kt, 0); 1951 1.8 christos return (NULL); 1952 1.1 itojun } 1953 1.1 itojun 1954 1.1 itojun void 1955 1.1 itojun pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr) 1956 1.1 itojun { 1957 1.1 itojun struct pfr_ktable *p, *q; 1958 1.1 itojun 1959 1.1 itojun for (p = SLIST_FIRST(workq); p; p = q) { 1960 1.1 itojun q = SLIST_NEXT(p, pfrkt_workq); 1961 1.1 itojun pfr_destroy_ktable(p, flushaddr); 1962 1.1 itojun } 1963 1.1 itojun } 1964 1.1 itojun 1965 1.1 itojun void 1966 1.1 itojun pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr) 1967 1.1 itojun { 1968 1.1 itojun struct pfr_kentryworkq addrq; 1969 1.1 itojun 1970 1.1 itojun if (flushaddr) { 1971 1.1 itojun pfr_enqueue_addrs(kt, &addrq, NULL, 0); 1972 1.1 itojun pfr_clean_node_mask(kt, &addrq); 1973 1.1 itojun pfr_destroy_kentries(&addrq); 1974 1.1 itojun } 1975 1.1 itojun if (kt->pfrkt_ip4 != NULL) 1976 1.11 christos free((void *)kt->pfrkt_ip4, M_RTABLE); 1977 1.1 itojun if (kt->pfrkt_ip6 != NULL) 1978 1.11 christos free((void *)kt->pfrkt_ip6, M_RTABLE); 1979 1.1 itojun if (kt->pfrkt_shadow != NULL) 1980 1.1 itojun pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr); 1981 1.1 itojun if (kt->pfrkt_rs != NULL) { 1982 1.1 itojun kt->pfrkt_rs->tables--; 1983 1.1 itojun pf_remove_if_empty_ruleset(kt->pfrkt_rs); 1984 1.1 itojun } 1985 1.1 itojun pool_put(&pfr_ktable_pl, kt); 1986 1.1 itojun } 1987 1.1 itojun 1988 1.1 itojun int 1989 1.1 itojun pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q) 1990 1.1 itojun { 1991 1.1 itojun int d; 1992 1.1 itojun 1993 1.1 itojun if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE))) 1994 1.1 itojun return (d); 1995 1.5 yamt return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor)); 1996 1.1 itojun } 1997 1.1 itojun 1998 1.1 itojun struct pfr_ktable * 1999 1.1 itojun pfr_lookup_table(struct pfr_table *tbl) 2000 1.1 itojun { 2001 1.1 itojun /* struct pfr_ktable start like a struct pfr_table */ 2002 1.1 itojun return (RB_FIND(pfr_ktablehead, &pfr_ktables, 2003 1.1 itojun (struct pfr_ktable *)tbl)); 2004 1.1 itojun } 2005 1.1 itojun 2006 1.1 itojun int 2007 1.1 itojun pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af) 2008 1.1 itojun { 2009 1.1 itojun struct pfr_kentry *ke = NULL; 2010 1.1 itojun int match; 2011 1.1 itojun 2012 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2013 1.1 itojun kt = kt->pfrkt_root; 2014 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2015 1.1 itojun return (0); 2016 1.1 itojun 2017 1.1 itojun switch (af) { 2018 1.5 yamt #ifdef INET 2019 1.1 itojun case AF_INET: 2020 1.1 itojun pfr_sin.sin_addr.s_addr = a->addr32[0]; 2021 1.1 itojun ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4); 2022 1.1 itojun if (ke && KENTRY_RNF_ROOT(ke)) 2023 1.1 itojun ke = NULL; 2024 1.1 itojun break; 2025 1.5 yamt #endif /* INET */ 2026 1.5 yamt #ifdef INET6 2027 1.1 itojun case AF_INET6: 2028 1.1 itojun bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr)); 2029 1.1 itojun ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6); 2030 1.1 itojun if (ke && KENTRY_RNF_ROOT(ke)) 2031 1.1 itojun ke = NULL; 2032 1.1 itojun break; 2033 1.5 yamt #endif /* INET6 */ 2034 1.1 itojun } 2035 1.1 itojun match = (ke && !ke->pfrke_not); 2036 1.1 itojun if (match) 2037 1.1 itojun kt->pfrkt_match++; 2038 1.1 itojun else 2039 1.1 itojun kt->pfrkt_nomatch++; 2040 1.1 itojun return (match); 2041 1.1 itojun } 2042 1.1 itojun 2043 1.1 itojun void 2044 1.1 itojun pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af, 2045 1.1 itojun u_int64_t len, int dir_out, int op_pass, int notrule) 2046 1.1 itojun { 2047 1.1 itojun struct pfr_kentry *ke = NULL; 2048 1.1 itojun 2049 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2050 1.1 itojun kt = kt->pfrkt_root; 2051 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2052 1.1 itojun return; 2053 1.1 itojun 2054 1.1 itojun switch (af) { 2055 1.5 yamt #ifdef INET 2056 1.1 itojun case AF_INET: 2057 1.1 itojun pfr_sin.sin_addr.s_addr = a->addr32[0]; 2058 1.1 itojun ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4); 2059 1.1 itojun if (ke && KENTRY_RNF_ROOT(ke)) 2060 1.1 itojun ke = NULL; 2061 1.1 itojun break; 2062 1.5 yamt #endif /* INET */ 2063 1.5 yamt #ifdef INET6 2064 1.1 itojun case AF_INET6: 2065 1.1 itojun bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr)); 2066 1.1 itojun ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6); 2067 1.1 itojun if (ke && KENTRY_RNF_ROOT(ke)) 2068 1.1 itojun ke = NULL; 2069 1.1 itojun break; 2070 1.5 yamt #endif /* INET6 */ 2071 1.5 yamt default: 2072 1.5 yamt ; 2073 1.1 itojun } 2074 1.1 itojun if ((ke == NULL || ke->pfrke_not) != notrule) { 2075 1.1 itojun if (op_pass != PFR_OP_PASS) 2076 1.1 itojun printf("pfr_update_stats: assertion failed.\n"); 2077 1.1 itojun op_pass = PFR_OP_XPASS; 2078 1.1 itojun } 2079 1.1 itojun kt->pfrkt_packets[dir_out][op_pass]++; 2080 1.1 itojun kt->pfrkt_bytes[dir_out][op_pass] += len; 2081 1.1 itojun if (ke != NULL && op_pass != PFR_OP_XPASS) { 2082 1.1 itojun ke->pfrke_packets[dir_out][op_pass]++; 2083 1.1 itojun ke->pfrke_bytes[dir_out][op_pass] += len; 2084 1.1 itojun } 2085 1.1 itojun } 2086 1.1 itojun 2087 1.1 itojun struct pfr_ktable * 2088 1.1 itojun pfr_attach_table(struct pf_ruleset *rs, char *name) 2089 1.1 itojun { 2090 1.1 itojun struct pfr_ktable *kt, *rt; 2091 1.1 itojun struct pfr_table tbl; 2092 1.1 itojun struct pf_anchor *ac = rs->anchor; 2093 1.1 itojun 2094 1.1 itojun bzero(&tbl, sizeof(tbl)); 2095 1.1 itojun strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name)); 2096 1.5 yamt if (ac != NULL) 2097 1.14 yamt strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor)); 2098 1.1 itojun kt = pfr_lookup_table(&tbl); 2099 1.1 itojun if (kt == NULL) { 2100 1.5 yamt kt = pfr_create_ktable(&tbl, time_second, 1); 2101 1.1 itojun if (kt == NULL) 2102 1.1 itojun return (NULL); 2103 1.1 itojun if (ac != NULL) { 2104 1.1 itojun bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor)); 2105 1.1 itojun rt = pfr_lookup_table(&tbl); 2106 1.1 itojun if (rt == NULL) { 2107 1.1 itojun rt = pfr_create_ktable(&tbl, 0, 1); 2108 1.1 itojun if (rt == NULL) { 2109 1.1 itojun pfr_destroy_ktable(kt, 0); 2110 1.1 itojun return (NULL); 2111 1.1 itojun } 2112 1.1 itojun pfr_insert_ktable(rt); 2113 1.1 itojun } 2114 1.1 itojun kt->pfrkt_root = rt; 2115 1.1 itojun } 2116 1.1 itojun pfr_insert_ktable(kt); 2117 1.1 itojun } 2118 1.1 itojun if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++) 2119 1.1 itojun pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED); 2120 1.1 itojun return (kt); 2121 1.1 itojun } 2122 1.1 itojun 2123 1.1 itojun void 2124 1.1 itojun pfr_detach_table(struct pfr_ktable *kt) 2125 1.1 itojun { 2126 1.1 itojun if (kt->pfrkt_refcnt[PFR_REFCNT_RULE] <= 0) 2127 1.1 itojun printf("pfr_detach_table: refcount = %d.\n", 2128 1.1 itojun kt->pfrkt_refcnt[PFR_REFCNT_RULE]); 2129 1.1 itojun else if (!--kt->pfrkt_refcnt[PFR_REFCNT_RULE]) 2130 1.1 itojun pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED); 2131 1.1 itojun } 2132 1.1 itojun 2133 1.1 itojun int 2134 1.1 itojun pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter, 2135 1.1 itojun struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af) 2136 1.1 itojun { 2137 1.5 yamt struct pfr_kentry *ke, *ke2 = (void *)0xdeadb; 2138 1.5 yamt struct pf_addr *addr = (void *)0xdeadb; 2139 1.1 itojun union sockaddr_union mask; 2140 1.1 itojun int idx = -1, use_counter = 0; 2141 1.1 itojun 2142 1.5 yamt if (af == AF_INET) 2143 1.5 yamt addr = (struct pf_addr *)&pfr_sin.sin_addr; 2144 1.5 yamt else if (af == AF_INET6) 2145 1.5 yamt addr = (struct pf_addr *)&pfr_sin6.sin6_addr; 2146 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL) 2147 1.1 itojun kt = kt->pfrkt_root; 2148 1.1 itojun if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) 2149 1.1 itojun return (-1); 2150 1.1 itojun 2151 1.1 itojun if (pidx != NULL) 2152 1.1 itojun idx = *pidx; 2153 1.1 itojun if (counter != NULL && idx >= 0) 2154 1.1 itojun use_counter = 1; 2155 1.1 itojun if (idx < 0) 2156 1.1 itojun idx = 0; 2157 1.1 itojun 2158 1.1 itojun _next_block: 2159 1.1 itojun ke = pfr_kentry_byidx(kt, idx, af); 2160 1.1 itojun if (ke == NULL) 2161 1.1 itojun return (1); 2162 1.1 itojun pfr_prepare_network(&pfr_mask, af, ke->pfrke_net); 2163 1.1 itojun *raddr = SUNION2PF(&ke->pfrke_sa, af); 2164 1.1 itojun *rmask = SUNION2PF(&pfr_mask, af); 2165 1.1 itojun 2166 1.1 itojun if (use_counter) { 2167 1.1 itojun /* is supplied address within block? */ 2168 1.1 itojun if (!PF_MATCHA(0, *raddr, *rmask, counter, af)) { 2169 1.1 itojun /* no, go to next block in table */ 2170 1.1 itojun idx++; 2171 1.1 itojun use_counter = 0; 2172 1.1 itojun goto _next_block; 2173 1.1 itojun } 2174 1.1 itojun PF_ACPY(addr, counter, af); 2175 1.1 itojun } else { 2176 1.1 itojun /* use first address of block */ 2177 1.1 itojun PF_ACPY(addr, *raddr, af); 2178 1.1 itojun } 2179 1.1 itojun 2180 1.1 itojun if (!KENTRY_NETWORK(ke)) { 2181 1.1 itojun /* this is a single IP address - no possible nested block */ 2182 1.1 itojun PF_ACPY(counter, addr, af); 2183 1.1 itojun *pidx = idx; 2184 1.1 itojun return (0); 2185 1.1 itojun } 2186 1.1 itojun for (;;) { 2187 1.1 itojun /* we don't want to use a nested block */ 2188 1.5 yamt if (af == AF_INET) 2189 1.5 yamt ke2 = (struct pfr_kentry *)rn_match(&pfr_sin, 2190 1.5 yamt kt->pfrkt_ip4); 2191 1.5 yamt else if (af == AF_INET6) 2192 1.5 yamt ke2 = (struct pfr_kentry *)rn_match(&pfr_sin6, 2193 1.5 yamt kt->pfrkt_ip6); 2194 1.1 itojun /* no need to check KENTRY_RNF_ROOT() here */ 2195 1.1 itojun if (ke2 == ke) { 2196 1.1 itojun /* lookup return the same block - perfect */ 2197 1.1 itojun PF_ACPY(counter, addr, af); 2198 1.1 itojun *pidx = idx; 2199 1.1 itojun return (0); 2200 1.1 itojun } 2201 1.1 itojun 2202 1.1 itojun /* we need to increase the counter past the nested block */ 2203 1.1 itojun pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net); 2204 1.1 itojun PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af); 2205 1.1 itojun PF_AINC(addr, af); 2206 1.1 itojun if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) { 2207 1.1 itojun /* ok, we reached the end of our main block */ 2208 1.1 itojun /* go to next block in table */ 2209 1.1 itojun idx++; 2210 1.1 itojun use_counter = 0; 2211 1.1 itojun goto _next_block; 2212 1.1 itojun } 2213 1.1 itojun } 2214 1.1 itojun } 2215 1.1 itojun 2216 1.1 itojun struct pfr_kentry * 2217 1.1 itojun pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af) 2218 1.1 itojun { 2219 1.1 itojun struct pfr_walktree w; 2220 1.1 itojun 2221 1.1 itojun bzero(&w, sizeof(w)); 2222 1.1 itojun w.pfrw_op = PFRW_POOL_GET; 2223 1.1 itojun w.pfrw_cnt = idx; 2224 1.1 itojun 2225 1.1 itojun switch (af) { 2226 1.5 yamt #ifdef INET 2227 1.1 itojun case AF_INET: 2228 1.1 itojun rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 2229 1.1 itojun return (w.pfrw_kentry); 2230 1.5 yamt #endif /* INET */ 2231 1.5 yamt #ifdef INET6 2232 1.1 itojun case AF_INET6: 2233 1.1 itojun rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 2234 1.1 itojun return (w.pfrw_kentry); 2235 1.5 yamt #endif /* INET6 */ 2236 1.1 itojun default: 2237 1.1 itojun return (NULL); 2238 1.1 itojun } 2239 1.1 itojun } 2240 1.1 itojun 2241 1.1 itojun void 2242 1.1 itojun pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn) 2243 1.1 itojun { 2244 1.1 itojun struct pfr_walktree w; 2245 1.1 itojun int s; 2246 1.1 itojun 2247 1.1 itojun bzero(&w, sizeof(w)); 2248 1.1 itojun w.pfrw_op = PFRW_DYNADDR_UPDATE; 2249 1.1 itojun w.pfrw_dyn = dyn; 2250 1.1 itojun 2251 1.1 itojun s = splsoftnet(); 2252 1.1 itojun dyn->pfid_acnt4 = 0; 2253 1.1 itojun dyn->pfid_acnt6 = 0; 2254 1.1 itojun if (!dyn->pfid_af || dyn->pfid_af == AF_INET) 2255 1.1 itojun rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w); 2256 1.1 itojun if (!dyn->pfid_af || dyn->pfid_af == AF_INET6) 2257 1.1 itojun rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w); 2258 1.1 itojun splx(s); 2259 1.1 itojun } 2260