| 319 | } |
| 320 | |
| 321 | int |
| 322 | pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size, |
| 323 | int *ndel, int flags) |
| 324 | { |
| 325 | struct pfr_ktable *kt; |
| 326 | struct pfr_kentryworkq workq; |
| 327 | struct pfr_kentry *p; |
| 328 | struct pfr_addr *ad; |
| 329 | int i, rv, xdel = 0, log = 1; |
| 330 | |
| 331 | PF_RULES_WASSERT(); |
| 332 | |
| 333 | ACCEPT_FLAGS(flags, PFR_FLAG_DUMMY | PFR_FLAG_FEEDBACK); |
| 334 | if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL)) |
| 335 | return (EINVAL); |
| 336 | kt = pfr_lookup_table(tbl); |
| 337 | if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE)) |
| 338 | return (ESRCH); |
| 339 | if (kt->pfrkt_flags & PFR_TFLAG_CONST) |
| 340 | return (EPERM); |
| 341 | /* |
| 342 | * there are two algorithms to choose from here. |
| 343 | * with: |
| 344 | * n: number of addresses to delete |
| 345 | * N: number of addresses in the table |
| 346 | * |
| 347 | * one is O(N) and is better for large 'n' |
| 348 | * one is O(n*LOG(N)) and is better for small 'n' |
| 349 | * |
| 350 | * following code try to decide which one is best. |
| 351 | */ |
| 352 | for (i = kt->pfrkt_cnt; i > 0; i >>= 1) |
| 353 | log++; |
| 354 | if (size > kt->pfrkt_cnt/log) { |
| 355 | /* full table scan */ |
| 356 | pfr_mark_addrs(kt); |
| 357 | } else { |
| 358 | /* iterate over addresses to delete */ |
| 359 | for (i = 0, ad = addr; i < size; i++, ad++) { |
| 360 | if (pfr_validate_addr(ad)) |
| 361 | return (EINVAL); |
| 362 | p = pfr_lookup_addr(kt, ad, 1); |
| 363 | if (p != NULL) |
| 364 | p->pfrke_mark = 0; |
| 365 | } |
| 366 | } |
| 367 | SLIST_INIT(&workq); |
| 368 | for (i = 0, ad = addr; i < size; i++, ad++) { |
| 369 | if (pfr_validate_addr(ad)) |
| 370 | senderr(EINVAL); |
| 371 | p = pfr_lookup_addr(kt, ad, 1); |
| 372 | if (flags & PFR_FLAG_FEEDBACK) { |
| 373 | if (p == NULL) |
| 374 | ad->pfra_fback = PFR_FB_NONE; |
| 375 | else if (p->pfrke_not != ad->pfra_not) |
| 376 | ad->pfra_fback = PFR_FB_CONFLICT; |
| 377 | else if (p->pfrke_mark) |
| 378 | ad->pfra_fback = PFR_FB_DUPLICATE; |
no test coverage detected