1 /* 2 * Copyright (C) 2012 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 */ 6 #if defined(KERNEL) || defined(_KERNEL) 7 # undef KERNEL 8 # undef _KERNEL 9 # define KERNEL 1 10 # define _KERNEL 1 11 #endif 12 #include <sys/param.h> 13 #include <sys/errno.h> 14 #include <sys/types.h> 15 #include <sys/time.h> 16 #include <sys/file.h> 17 #if defined(__FreeBSD__) && defined(_KERNEL) 18 # include <sys/fcntl.h> 19 # include <sys/filio.h> 20 #else 21 # include <sys/ioctl.h> 22 #endif 23 #if !defined(_KERNEL) 24 # include <stdio.h> 25 # include <string.h> 26 # include <stdlib.h> 27 # define _KERNEL 28 # include <sys/uio.h> 29 # undef _KERNEL 30 #endif 31 #include <sys/socket.h> 32 #include <net/if.h> 33 #if defined(__FreeBSD__) 34 # include <sys/cdefs.h> 35 # include <sys/proc.h> 36 #endif 37 #if defined(_KERNEL) 38 # include <sys/systm.h> 39 # if !defined(__SVR4) 40 # include <sys/mbuf.h> 41 # endif 42 #else 43 # include "ipf.h" 44 #endif 45 #include <netinet/in.h> 46 47 #include "netinet/ip_compat.h" 48 #include "netinet/ip_fil.h" 49 #include "netinet/ip_lookup.h" 50 #include "netinet/ip_pool.h" 51 #include "netinet/ip_htable.h" 52 #include "netinet/ip_dstlist.h" 53 /* END OF INCLUDES */ 54 55 56 /* 57 * In this file, ip_pool.c, ip_htable.c and ip_dstlist.c, you will find the 58 * range for unit is [-1,IPL_LOGMAX]. The -1 is considered to be a valid number 59 * and represents a "wildcard" or "all" units (IPL_LOGALL). The reason for not 60 * starting the numbering at 0 is because the numbers [0,IPL_LOGMAX] correspond 61 * to the minor device number for their respective device. Thus where there is 62 * array indexing on the unit, +1 is used to map [-1.IPL_LOGMAX] to 63 * [0.POOL_LOOKUP_MAX]. 64 */ 65 static int ipf_lookup_addnode(ipf_main_softc_t *, caddr_t, int); 66 static int ipf_lookup_delnode(ipf_main_softc_t *, caddr_t, int); 67 static int ipf_lookup_addtable(ipf_main_softc_t *, caddr_t); 68 static int ipf_lookup_deltable(ipf_main_softc_t *, caddr_t); 69 static int ipf_lookup_stats(ipf_main_softc_t *, caddr_t); 70 static int ipf_lookup_flush(ipf_main_softc_t *, caddr_t); 71 static int ipf_lookup_iterate(ipf_main_softc_t *, void *, int, void *); 72 static int ipf_lookup_deltok(ipf_main_softc_t *, void *, int, void *); 73 74 #define MAX_BACKENDS 3 75 static ipf_lookup_t *backends[MAX_BACKENDS] = { 76 &ipf_pool_backend, 77 &ipf_htable_backend, 78 &ipf_dstlist_backend 79 }; 80 81 82 typedef struct ipf_lookup_softc_s { 83 void *ipf_back[MAX_BACKENDS]; 84 } ipf_lookup_softc_t; 85 86 87 /* ------------------------------------------------------------------------ */ 88 /* Function: ipf_lookup_init */ 89 /* Returns: int - 0 = success, else error */ 90 /* Parameters: softc(I) - pointer to soft context main structure */ 91 /* */ 92 /* Initialise all of the subcomponents of the lookup infrstructure. */ 93 /* ------------------------------------------------------------------------ */ 94 void * 95 ipf_lookup_soft_create(ipf_main_softc_t *softc) 96 { 97 ipf_lookup_softc_t *softl; 98 ipf_lookup_t **l; 99 int i; 100 101 KMALLOC(softl, ipf_lookup_softc_t *); 102 if (softl == NULL) 103 return (NULL); 104 105 bzero((char *)softl, sizeof(*softl)); 106 107 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 108 softl->ipf_back[i] = (*(*l)->ipfl_create)(softc); 109 if (softl->ipf_back[i] == NULL) { 110 ipf_lookup_soft_destroy(softc, softl); 111 return (NULL); 112 } 113 } 114 115 return (softl); 116 } 117 118 119 /* ------------------------------------------------------------------------ */ 120 /* Function: ipf_lookup_soft_init */ 121 /* Returns: int - 0 = success, else error */ 122 /* Parameters: softc(I) - pointer to soft context main structure */ 123 /* arg(I) - pointer to local context to use */ 124 /* */ 125 /* Initialise all of the subcomponents of the lookup infrstructure. */ 126 /* ------------------------------------------------------------------------ */ 127 int 128 ipf_lookup_soft_init(ipf_main_softc_t *softc, void *arg) 129 { 130 ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg; 131 int err = 0; 132 int i; 133 134 for (i = 0; i < MAX_BACKENDS; i++) { 135 err = (*backends[i]->ipfl_init)(softc, softl->ipf_back[i]); 136 if (err != 0) 137 break; 138 } 139 140 return (err); 141 } 142 143 144 /* ------------------------------------------------------------------------ */ 145 /* Function: ipf_lookup_soft_fini */ 146 /* Returns: int - 0 = success, else error */ 147 /* Parameters: softc(I) - pointer to soft context main structure */ 148 /* arg(I) - pointer to local context to use */ 149 /* */ 150 /* Call the fini function in each backend to cleanup all allocated data. */ 151 /* ------------------------------------------------------------------------ */ 152 int 153 ipf_lookup_soft_fini(ipf_main_softc_t *softc, void *arg) 154 { 155 ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg; 156 int i; 157 158 for (i = 0; i < MAX_BACKENDS; i++) { 159 if (softl->ipf_back[i] != NULL) 160 (*backends[i]->ipfl_fini)(softc, 161 softl->ipf_back[i]); 162 } 163 164 return (0); 165 } 166 167 168 /* ------------------------------------------------------------------------ */ 169 /* Function: ipf_lookup_expire */ 170 /* Returns: Nil */ 171 /* Parameters: softc(I) - pointer to soft context main structure */ 172 /* */ 173 /* Step through each of the backends and call their expire functions, */ 174 /* allowing them to delete any lifetime limited data. */ 175 /* ------------------------------------------------------------------------ */ 176 void 177 ipf_lookup_expire(ipf_main_softc_t *softc) 178 { 179 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 180 int i; 181 182 WRITE_ENTER(&softc->ipf_poolrw); 183 for (i = 0; i < MAX_BACKENDS; i++) 184 (*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]); 185 RWLOCK_EXIT(&softc->ipf_poolrw); 186 } 187 188 189 /* ------------------------------------------------------------------------ */ 190 /* Function: ipf_lookup_softc_destroy */ 191 /* Returns: int - 0 = success, else error */ 192 /* Parameters: softc(I) - pointer to soft context main structure */ 193 /* arg(I) - pointer to local context to use */ 194 /* */ 195 /* Free up all pool related memory that has been allocated whilst IPFilter */ 196 /* has been running. Also, do any other deinitialisation required such */ 197 /* ipf_lookup_init() can be called again, safely. */ 198 /* ------------------------------------------------------------------------ */ 199 void 200 ipf_lookup_soft_destroy(ipf_main_softc_t *softc, void *arg) 201 { 202 ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg; 203 int i; 204 205 for (i = 0; i < MAX_BACKENDS; i++) { 206 if (softl->ipf_back[i] != NULL) 207 (*backends[i]->ipfl_destroy)(softc, 208 softl->ipf_back[i]); 209 } 210 211 KFREE(softl); 212 } 213 214 215 /* ------------------------------------------------------------------------ */ 216 /* Function: ipf_lookup_ioctl */ 217 /* Returns: int - 0 = success, else error */ 218 /* Parameters: softc(I) - pointer to soft context main structure */ 219 /* arg(I) - pointer to local context to use */ 220 /* data(IO) - pointer to ioctl data to be copied to/from user */ 221 /* space. */ 222 /* cmd(I) - ioctl command number */ 223 /* mode(I) - file mode bits used with open */ 224 /* uid(I) - uid of process doing ioctl */ 225 /* ctx(I) - pointer that represents context for uid */ 226 /* */ 227 /* Handle ioctl commands sent to the ioctl device. For the most part, this */ 228 /* involves just calling another function to handle the specifics of each */ 229 /* command. */ 230 /* ------------------------------------------------------------------------ */ 231 int 232 ipf_lookup_ioctl(ipf_main_softc_t *softc, caddr_t data, ioctlcmd_t cmd, 233 int mode, int uid, void *ctx) 234 { 235 int err; 236 SPL_INT(s); 237 238 mode = mode; /* LINT */ 239 240 SPL_NET(s); 241 242 switch (cmd) 243 { 244 case SIOCLOOKUPADDNODE : 245 case SIOCLOOKUPADDNODEW : 246 WRITE_ENTER(&softc->ipf_poolrw); 247 err = ipf_lookup_addnode(softc, data, uid); 248 RWLOCK_EXIT(&softc->ipf_poolrw); 249 break; 250 251 case SIOCLOOKUPDELNODE : 252 case SIOCLOOKUPDELNODEW : 253 WRITE_ENTER(&softc->ipf_poolrw); 254 err = ipf_lookup_delnode(softc, data, uid); 255 RWLOCK_EXIT(&softc->ipf_poolrw); 256 break; 257 258 case SIOCLOOKUPADDTABLE : 259 WRITE_ENTER(&softc->ipf_poolrw); 260 err = ipf_lookup_addtable(softc, data); 261 RWLOCK_EXIT(&softc->ipf_poolrw); 262 break; 263 264 case SIOCLOOKUPDELTABLE : 265 WRITE_ENTER(&softc->ipf_poolrw); 266 err = ipf_lookup_deltable(softc, data); 267 RWLOCK_EXIT(&softc->ipf_poolrw); 268 break; 269 270 case SIOCLOOKUPSTAT : 271 case SIOCLOOKUPSTATW : 272 WRITE_ENTER(&softc->ipf_poolrw); 273 err = ipf_lookup_stats(softc, data); 274 RWLOCK_EXIT(&softc->ipf_poolrw); 275 break; 276 277 case SIOCLOOKUPFLUSH : 278 WRITE_ENTER(&softc->ipf_poolrw); 279 err = ipf_lookup_flush(softc, data); 280 RWLOCK_EXIT(&softc->ipf_poolrw); 281 break; 282 283 case SIOCLOOKUPITER : 284 err = ipf_lookup_iterate(softc, data, uid, ctx); 285 break; 286 287 case SIOCIPFDELTOK : 288 err = ipf_lookup_deltok(softc, data, uid, ctx); 289 break; 290 291 default : 292 IPFERROR(50001); 293 err = EINVAL; 294 break; 295 } 296 SPL_X(s); 297 return (err); 298 } 299 300 301 /* ------------------------------------------------------------------------ */ 302 /* Function: ipf_lookup_addnode */ 303 /* Returns: int - 0 = success, else error */ 304 /* Parameters: softc(I) - pointer to soft context main structure */ 305 /* data(I) - pointer to data from ioctl call */ 306 /* */ 307 /* Add a new data node to a lookup structure. First, check to see if the */ 308 /* parent structure refered to by name exists and if it does, then go on to */ 309 /* add a node to it. */ 310 /* ------------------------------------------------------------------------ */ 311 static int 312 ipf_lookup_addnode(ipf_main_softc_t *softc, caddr_t data, int uid) 313 { 314 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 315 iplookupop_t op; 316 ipf_lookup_t **l; 317 int err; 318 int i; 319 320 err = BCOPYIN(data, &op, sizeof(op)); 321 if (err != 0) { 322 IPFERROR(50002); 323 return (EFAULT); 324 } 325 326 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && 327 (op.iplo_unit != IPLT_ALL)) { 328 IPFERROR(50003); 329 return (EINVAL); 330 } 331 332 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 333 334 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 335 if (op.iplo_type == (*l)->ipfl_type) { 336 err = (*(*l)->ipfl_node_add)(softc, 337 softl->ipf_back[i], 338 &op, uid); 339 break; 340 } 341 } 342 343 if (i == MAX_BACKENDS) { 344 IPFERROR(50012); 345 err = EINVAL; 346 } 347 348 return (err); 349 } 350 351 352 /* ------------------------------------------------------------------------ */ 353 /* Function: ipf_lookup_delnode */ 354 /* Returns: int - 0 = success, else error */ 355 /* Parameters: softc(I) - pointer to soft context main structure */ 356 /* data(I) - pointer to data from ioctl call */ 357 /* */ 358 /* Delete a node from a lookup table by first looking for the table it is */ 359 /* in and then deleting the entry that gets found. */ 360 /* ------------------------------------------------------------------------ */ 361 static int 362 ipf_lookup_delnode(ipf_main_softc_t *softc, caddr_t data, int uid) 363 { 364 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 365 iplookupop_t op; 366 ipf_lookup_t **l; 367 int err; 368 int i; 369 370 err = BCOPYIN(data, &op, sizeof(op)); 371 if (err != 0) { 372 IPFERROR(50042); 373 return (EFAULT); 374 } 375 376 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && 377 (op.iplo_unit != IPLT_ALL)) { 378 IPFERROR(50013); 379 return (EINVAL); 380 } 381 382 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 383 384 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 385 if (op.iplo_type == (*l)->ipfl_type) { 386 err = (*(*l)->ipfl_node_del)(softc, softl->ipf_back[i], 387 &op, uid); 388 break; 389 } 390 } 391 392 if (i == MAX_BACKENDS) { 393 IPFERROR(50021); 394 err = EINVAL; 395 } 396 return (err); 397 } 398 399 400 /* ------------------------------------------------------------------------ */ 401 /* Function: ipf_lookup_addtable */ 402 /* Returns: int - 0 = success, else error */ 403 /* Parameters: softc(I) - pointer to soft context main structure */ 404 /* data(I) - pointer to data from ioctl call */ 405 /* */ 406 /* Create a new lookup table, if one doesn't already exist using the name */ 407 /* for this one. */ 408 /* ------------------------------------------------------------------------ */ 409 static int 410 ipf_lookup_addtable(ipf_main_softc_t *softc, caddr_t data) 411 { 412 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 413 iplookupop_t op; 414 ipf_lookup_t **l; 415 int err, i; 416 417 err = BCOPYIN(data, &op, sizeof(op)); 418 if (err != 0) { 419 IPFERROR(50022); 420 return (EFAULT); 421 } 422 423 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && 424 (op.iplo_unit != IPLT_ALL)) { 425 IPFERROR(50023); 426 return (EINVAL); 427 } 428 429 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 430 431 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 432 if (op.iplo_type == (*l)->ipfl_type) { 433 err = (*(*l)->ipfl_table_add)(softc, 434 softl->ipf_back[i], 435 &op); 436 break; 437 } 438 } 439 440 if (i == MAX_BACKENDS) { 441 IPFERROR(50026); 442 err = EINVAL; 443 } 444 445 /* 446 * For anonymous pools, copy back the operation struct because in the 447 * case of success it will contain the new table's name. 448 */ 449 if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) { 450 err = BCOPYOUT(&op, data, sizeof(op)); 451 if (err != 0) { 452 IPFERROR(50027); 453 err = EFAULT; 454 } 455 } 456 457 return (err); 458 } 459 460 461 /* ------------------------------------------------------------------------ */ 462 /* Function: ipf_lookup_deltable */ 463 /* Returns: int - 0 = success, else error */ 464 /* Parameters: softc(I) - pointer to soft context main structure */ 465 /* data(I) - pointer to data from ioctl call */ 466 /* */ 467 /* Decodes ioctl request to remove a particular hash table or pool and */ 468 /* calls the relevant function to do the cleanup. */ 469 /* ------------------------------------------------------------------------ */ 470 static int 471 ipf_lookup_deltable(ipf_main_softc_t *softc, caddr_t data) 472 { 473 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 474 iplookupop_t op; 475 ipf_lookup_t **l; 476 int err, i; 477 478 err = BCOPYIN(data, &op, sizeof(op)); 479 if (err != 0) { 480 IPFERROR(50028); 481 return (EFAULT); 482 } 483 484 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && 485 (op.iplo_unit != IPLT_ALL)) { 486 IPFERROR(50029); 487 return (EINVAL); 488 } 489 490 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0'; 491 492 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 493 if (op.iplo_type == (*l)->ipfl_type) { 494 err = (*(*l)->ipfl_table_del)(softc, 495 softl->ipf_back[i], 496 &op); 497 break; 498 } 499 } 500 501 if (i == MAX_BACKENDS) { 502 IPFERROR(50030); 503 err = EINVAL; 504 } 505 return (err); 506 } 507 508 509 /* ------------------------------------------------------------------------ */ 510 /* Function: ipf_lookup_stats */ 511 /* Returns: int - 0 = success, else error */ 512 /* Parameters: softc(I) - pointer to soft context main structure */ 513 /* data(I) - pointer to data from ioctl call */ 514 /* */ 515 /* Copy statistical information from inside the kernel back to user space. */ 516 /* ------------------------------------------------------------------------ */ 517 static int 518 ipf_lookup_stats(ipf_main_softc_t *softc, caddr_t data) 519 { 520 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 521 iplookupop_t op; 522 ipf_lookup_t **l; 523 int err; 524 int i; 525 526 err = BCOPYIN(data, &op, sizeof(op)); 527 if (err != 0) { 528 IPFERROR(50031); 529 return (EFAULT); 530 } 531 532 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) && 533 (op.iplo_unit != IPLT_ALL)) { 534 IPFERROR(50032); 535 return (EINVAL); 536 } 537 538 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 539 if (op.iplo_type == (*l)->ipfl_type) { 540 err = (*(*l)->ipfl_stats_get)(softc, 541 softl->ipf_back[i], 542 &op); 543 break; 544 } 545 } 546 547 if (i == MAX_BACKENDS) { 548 IPFERROR(50033); 549 err = EINVAL; 550 } 551 552 return (err); 553 } 554 555 556 /* ------------------------------------------------------------------------ */ 557 /* Function: ipf_lookup_flush */ 558 /* Returns: int - 0 = success, else error */ 559 /* Parameters: softc(I) - pointer to soft context main structure */ 560 /* data(I) - pointer to data from ioctl call */ 561 /* */ 562 /* A flush is called when we want to flush all the nodes from a particular */ 563 /* entry in the hash table/pool or want to remove all groups from those. */ 564 /* ------------------------------------------------------------------------ */ 565 static int 566 ipf_lookup_flush(ipf_main_softc_t *softc, caddr_t data) 567 { 568 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 569 int err, unit, num, type, i; 570 iplookupflush_t flush; 571 ipf_lookup_t **l; 572 573 err = BCOPYIN(data, &flush, sizeof(flush)); 574 if (err != 0) { 575 IPFERROR(50034); 576 return (EFAULT); 577 } 578 579 unit = flush.iplf_unit; 580 if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) { 581 IPFERROR(50035); 582 return (EINVAL); 583 } 584 585 flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0'; 586 587 type = flush.iplf_type; 588 IPFERROR(50036); 589 err = EINVAL; 590 num = 0; 591 592 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 593 if (type == (*l)->ipfl_type || type == IPLT_ALL) { 594 err = 0; 595 num += (*(*l)->ipfl_flush)(softc, 596 softl->ipf_back[i], 597 &flush); 598 } 599 } 600 601 if (err == 0) { 602 flush.iplf_count = num; 603 err = BCOPYOUT(&flush, data, sizeof(flush)); 604 if (err != 0) { 605 IPFERROR(50037); 606 err = EFAULT; 607 } 608 } 609 return (err); 610 } 611 612 613 /* ------------------------------------------------------------------------ */ 614 /* Function: ipf_lookup_delref */ 615 /* Returns: void */ 616 /* Parameters: softc(I) - pointer to soft context main structure */ 617 /* type(I) - table type to operate on */ 618 /* ptr(I) - pointer to object to remove reference for */ 619 /* */ 620 /* This function organises calling the correct deref function for a given */ 621 /* type of object being passed into it. */ 622 /* ------------------------------------------------------------------------ */ 623 void 624 ipf_lookup_deref(ipf_main_softc_t *softc, int type, void *ptr) 625 { 626 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 627 int i; 628 629 if (ptr == NULL) 630 return; 631 632 for (i = 0; i < MAX_BACKENDS; i++) { 633 if (type == backends[i]->ipfl_type) { 634 WRITE_ENTER(&softc->ipf_poolrw); 635 (*backends[i]->ipfl_table_deref)(softc, 636 softl->ipf_back[i], 637 ptr); 638 RWLOCK_EXIT(&softc->ipf_poolrw); 639 break; 640 } 641 } 642 } 643 644 645 /* ------------------------------------------------------------------------ */ 646 /* Function: ipf_lookup_iterate */ 647 /* Returns: int - 0 = success, else error */ 648 /* Parameters: softc(I) - pointer to soft context main structure */ 649 /* data(I) - pointer to data from ioctl call */ 650 /* uid(I) - uid of caller */ 651 /* ctx(I) - pointer to give the uid context */ 652 /* */ 653 /* Decodes ioctl request to step through either hash tables or pools. */ 654 /* ------------------------------------------------------------------------ */ 655 static int 656 ipf_lookup_iterate(ipf_main_softc_t *softc, void *data, int uid, void *ctx) 657 { 658 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 659 ipflookupiter_t iter; 660 ipftoken_t *token; 661 int err, i; 662 SPL_INT(s); 663 664 err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER); 665 if (err != 0) 666 return (err); 667 668 if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) { 669 IPFERROR(50038); 670 return (EINVAL); 671 } 672 673 if (iter.ili_ival != IPFGENITER_LOOKUP) { 674 IPFERROR(50039); 675 return (EINVAL); 676 } 677 678 SPL_SCHED(s); 679 token = ipf_token_find(softc, iter.ili_key, uid, ctx); 680 if (token == NULL) { 681 SPL_X(s); 682 IPFERROR(50040); 683 return (ESRCH); 684 } 685 686 for (i = 0; i < MAX_BACKENDS; i++) { 687 if (iter.ili_type == backends[i]->ipfl_type) { 688 err = (*backends[i]->ipfl_iter_next)(softc, 689 softl->ipf_back[i], 690 token, &iter); 691 break; 692 } 693 } 694 SPL_X(s); 695 696 if (i == MAX_BACKENDS) { 697 IPFERROR(50041); 698 err = EINVAL; 699 } 700 701 WRITE_ENTER(&softc->ipf_tokens); 702 ipf_token_deref(softc, token); 703 RWLOCK_EXIT(&softc->ipf_tokens); 704 705 return (err); 706 } 707 708 709 /* ------------------------------------------------------------------------ */ 710 /* Function: ipf_lookup_iterderef */ 711 /* Returns: void */ 712 /* Parameters: softc(I) - pointer to soft context main structure */ 713 /* type(I) - backend type to iterate through */ 714 /* data(I) - pointer to data from ioctl call */ 715 /* */ 716 /* Decodes ioctl request to remove a particular hash table or pool and */ 717 /* calls the relevant function to do the cleanup. */ 718 /* Because each of the backend types has a different data structure, */ 719 /* iteration is limited to one type at a time (i.e. it is not permitted to */ 720 /* go on from pool types to hash types as part of the "get next".) */ 721 /* ------------------------------------------------------------------------ */ 722 void 723 ipf_lookup_iterderef(ipf_main_softc_t *softc, u_32_t type, void *data) 724 { 725 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 726 struct iplookupiterkey *lkey; 727 iplookupiterkey_t key; 728 int i; 729 730 key.ilik_key = type; 731 lkey = &key.ilik_unstr; 732 733 if (lkey->ilik_ival != IPFGENITER_LOOKUP) 734 return; 735 736 WRITE_ENTER(&softc->ipf_poolrw); 737 738 for (i = 0; i < MAX_BACKENDS; i++) { 739 if (lkey->ilik_type == backends[i]->ipfl_type) { 740 (*backends[i]->ipfl_iter_deref)(softc, 741 softl->ipf_back[i], 742 lkey->ilik_otype, 743 lkey->ilik_unit, 744 data); 745 break; 746 } 747 } 748 RWLOCK_EXIT(&softc->ipf_poolrw); 749 } 750 751 752 /* ------------------------------------------------------------------------ */ 753 /* Function: ipf_lookup_deltok */ 754 /* Returns: int - 0 = success, else error */ 755 /* Parameters: softc(I) - pointer to soft context main structure */ 756 /* data(I) - pointer to data from ioctl call */ 757 /* uid(I) - uid of caller */ 758 /* ctx(I) - pointer to give the uid context */ 759 /* */ 760 /* Deletes the token identified by the combination of (type,uid,ctx) */ 761 /* "key" is a combination of the table type, iterator type and the unit for */ 762 /* which the token was being used. */ 763 /* ------------------------------------------------------------------------ */ 764 int 765 ipf_lookup_deltok(ipf_main_softc_t *softc, void *data, int uid, void *ctx) 766 { 767 int error, key; 768 SPL_INT(s); 769 770 SPL_SCHED(s); 771 error = BCOPYIN(data, &key, sizeof(key)); 772 if (error == 0) 773 error = ipf_token_del(softc, key, uid, ctx); 774 SPL_X(s); 775 return (error); 776 } 777 778 779 /* ------------------------------------------------------------------------ */ 780 /* Function: ipf_lookup_res_num */ 781 /* Returns: void * - NULL = failure, else success. */ 782 /* Parameters: softc(I) - pointer to soft context main structure */ 783 /* unit(I) - device for which this is for */ 784 /* type(I) - type of lookup these parameters are for. */ 785 /* number(I) - table number to use when searching */ 786 /* funcptr(IO) - pointer to pointer for storing IP address */ 787 /* searching function. */ 788 /* */ 789 /* Search for the "table" number passed in amongst those configured for */ 790 /* that particular type. If the type is recognised then the function to */ 791 /* call to do the IP address search will be change, regardless of whether */ 792 /* or not the "table" number exists. */ 793 /* ------------------------------------------------------------------------ */ 794 void * 795 ipf_lookup_res_num(ipf_main_softc_t *softc, int unit, u_int type, u_int number, 796 lookupfunc_t *funcptr) 797 { 798 char name[FR_GROUPLEN]; 799 800 (void) snprintf(name, sizeof(name), "%u", number); 801 802 return (ipf_lookup_res_name(softc, unit, type, name, funcptr)); 803 } 804 805 806 /* ------------------------------------------------------------------------ */ 807 /* Function: ipf_lookup_res_name */ 808 /* Returns: void * - NULL = failure, else success. */ 809 /* Parameters: softc(I) - pointer to soft context main structure */ 810 /* unit(I) - device for which this is for */ 811 /* type(I) - type of lookup these parameters are for. */ 812 /* name(I) - table name to use when searching */ 813 /* funcptr(IO) - pointer to pointer for storing IP address */ 814 /* searching function. */ 815 /* */ 816 /* Search for the "table" number passed in amongst those configured for */ 817 /* that particular type. If the type is recognised then the function to */ 818 /* call to do the IP address search will be changed, regardless of whether */ 819 /* or not the "table" number exists. */ 820 /* ------------------------------------------------------------------------ */ 821 void * 822 ipf_lookup_res_name(ipf_main_softc_t *softc, int unit, u_int type, char *name, 823 lookupfunc_t *funcptr) 824 { 825 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 826 ipf_lookup_t **l; 827 void *ptr = NULL; 828 int i; 829 830 READ_ENTER(&softc->ipf_poolrw); 831 832 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 833 if (type == (*l)->ipfl_type) { 834 ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i], 835 unit, name); 836 if (ptr != NULL && funcptr != NULL) { 837 *funcptr = (*l)->ipfl_addr_find; 838 } 839 break; 840 } 841 } 842 843 if (i == MAX_BACKENDS) { 844 ptr = NULL; 845 if (funcptr != NULL) 846 *funcptr = NULL; 847 } 848 849 RWLOCK_EXIT(&softc->ipf_poolrw); 850 851 return (ptr); 852 } 853 854 855 /* ------------------------------------------------------------------------ */ 856 /* Function: ipf_lookup_find_htable */ 857 /* Returns: void * - NULL = failure, else success. */ 858 /* Parameters: softc(I) - pointer to soft context main structure */ 859 /* unit(I) - device for which this is for */ 860 /* name(I) - table name to use when searching */ 861 /* */ 862 /* To support the group-map feature, where a hash table maps address */ 863 /* networks to rule group numbers, we need to expose a function that uses */ 864 /* only the hash table backend. */ 865 /* ------------------------------------------------------------------------ */ 866 void * 867 ipf_lookup_find_htable(ipf_main_softc_t *softc, int unit, char *name) 868 { 869 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 870 ipf_lookup_t **l; 871 void *tab = NULL; 872 int i; 873 874 READ_ENTER(&softc->ipf_poolrw); 875 876 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 877 if (IPLT_HASH == (*l)->ipfl_type) { 878 tab = ipf_htable_find(softl->ipf_back[i], unit, name); 879 break; 880 } 881 882 RWLOCK_EXIT(&softc->ipf_poolrw); 883 884 return (tab); 885 } 886 887 888 /* ------------------------------------------------------------------------ */ 889 /* Function: ipf_lookup_sync */ 890 /* Returns: void */ 891 /* Parameters: softc(I) - pointer to soft context main structure */ 892 /* */ 893 /* This function is the interface that the machine dependent sync functions */ 894 /* call when a network interface name change occurs. It then calls the sync */ 895 /* functions of the lookup implementations - if they have one. */ 896 /* ------------------------------------------------------------------------ */ 897 /*ARGSUSED*/ 898 void 899 ipf_lookup_sync(ipf_main_softc_t *softc, void *ifp) 900 { 901 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 902 ipf_lookup_t **l; 903 int i; 904 905 READ_ENTER(&softc->ipf_poolrw); 906 907 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 908 if ((*l)->ipfl_sync != NULL) 909 (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]); 910 911 RWLOCK_EXIT(&softc->ipf_poolrw); 912 } 913 914 915 #ifndef _KERNEL 916 void 917 ipf_lookup_dump(ipf_main_softc_t *softc, void *arg) 918 { 919 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 920 ipf_lookup_t **l; 921 int i; 922 923 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 924 if (IPLT_POOL == (*l)->ipfl_type) { 925 ipf_pool_dump(softc, softl->ipf_back[i]); 926 break; 927 } 928 929 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 930 if (IPLT_HASH == (*l)->ipfl_type) { 931 ipf_htable_dump(softc, softl->ipf_back[i]); 932 break; 933 } 934 } 935 #endif 936