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