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