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